我一个新的使用Hibernate缓存(一级,二级和查询缓存)。
我的项目是使用SpringMVC和JPA配置的。
我正在使用下面的JUnit测试用例测试一级缓存。
public class FirstLevelCacheTest
{
private static final Logger logger = LoggerFactory.getLogger(FirstLevelCacheTest.class);
@PersistenceContext
private EntityManager entityManager;
@Test
public void testFirstLevelCacheTest()
{
Long clientId = 1L;
// fetch the client entity from database first time
Client client1 = entityManager.find(Client.class, clientId);
logger.debug("Client Name : {}", client1.getName());
// fetch the client entity again
client1 = entityManager.find(Client.class, clientId);
logger.debug("Client Name : {}", client1.getName());
}
}
我的实体类定义为:
@Entity
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@Table(name = "client")
public class Client extends BaseModel
{
// instance variable declaration
// getter and setter methods for instance variables
}
如果默认情况下启用了一级缓存,则应该执行一次本机查询。但我在执行此查询时得到以下结果:
Hibernate: select client0_.id as id0_0_, client0_.created as created0_0_, client0_.createdBy as createdBy0_0_, client0_.updated as updated0_0_, client0_.updatedBy as updatedBy0_0_, client0_.contactNo as contactNo0_0_, client0_.contactPerson as contactP7_0_0_, client0_.contactPersonEmail as contactP8_0_0_, client0_.contactPersonNo as contactP9_0_0_, client0_.email as email0_0_, client0_.name as name0_0_ from client client0_ where client0_.id=?
[main] DEBUG Client Name : Client1
Hibernate: select client0_.id as id0_0_, client0_.created as created0_0_, client0_.createdBy as createdBy0_0_, client0_.updated as updated0_0_, client0_.updatedBy as updatedBy0_0_, client0_.contactNo as contactNo0_0_, client0_.contactPerson as contactP7_0_0_, client0_.contactPersonEmail as contactP8_0_0_, client0_.contactPersonNo as contactP9_0_0_, client0_.email as email0_0_, client0_.name as name0_0_ from client client0_ where client0_.id=?
[main] DEBUG Client Name : Client1
以下是我的持久性相关配置:
@Configuration
@EnableTransactionManagement
public class PersistanceConfig
{
// injection
private String[] PACKAGES_TO_SCAN = new String[] { "com.mypackage1", "com.mypackage2" };
@Bean
public DataSource dataSource()
{
// dataSource setting 'com.mysql.jdbc.Driver' as a jdbc driver
}
private Properties jpaProperties()
{
Properties properties = new Properties();
properties.put(AvailableSettings.DIALECT, hibernateDialect);
properties.put(AvailableSettings.SHOW_SQL, hibernateShowSql);
// 2nd level cache
properties.put("hibernate.cache.use_second_level_cache", true);
properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");
return properties;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
{
// entity manager settings using dataSource and jpaProperties
}
@Bean
public JpaTransactionManager transactionManager()
{
// transaction manager settings using entityManagerFactory
}
}
有人能帮我解决一个问题或者我做错了什么吗?
提前感谢!
@Transactional负责处理从会话工厂获取会话对象,从entityManagerFactory一级缓存获取entityManger对象,发生在会话级别或entityManger级别,所以@Tranaction注释在这里非常重要
我已经在一个简单的命令行应用程序中测试了你的场景,无法重现这个问题。用Hibernate 4.0.1和Hibernate 4.3测试。基本上,我在事务之外提取了两次相同的实体,第二次SQL查询没有执行。重要提示:我一个接一个地调用EntityManager.find()
,它们之间没有任何其他操作(如打开一个事务,这将触发另一个SQL选择)。
我向你推荐以下几点:1。确保您还查看了数据库服务器的日志(以确保Hibernate不会记录查询,尽管它不会发送查询)。2.将Hibernate升级到新版本。
另一个注意事项:据我所知,Hibernate不需要使用这样的缓存。
我用过的persistence.xml:
<persistence version="2.0" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="my-PU" transaction-type="RESOURCE_LOCAL">
<!--<provider>org.hibernate.ejb.HibernatePersistence</provider>-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.package.Entity</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.hbm2ddl.import_files" valu="sql/import-users.sql"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
您需要用@Transactional
注释测试方法,或者使用SpringTransactionTemboard
。
即使检索实体不需要事务,在一个实体中分组多个调用也会清楚地指定持久性上下文边界(从何处开始,从何处结束)。
要复制第一级缓存,您需要在整个测试方法中使用相同的工作单元,并且使用@Transactional
注释测试将启动一个事务(绑定到当前执行的持久性上下文事务的Spring逻辑事务,该事务与实际的物理数据库事务相关)。
当测试方法结束时,事务通常会回滚,因此不会将任何更改传播到任何后续测试,但在当前执行的测试方法中,您可以看到自己的更改,这是ACID中的隔离属性。
本文向大家介绍说一下 MyBatis 的一级缓存和二级缓存?相关面试题,主要包含被问及说一下 MyBatis 的一级缓存和二级缓存?时的应答技巧和注意事项,需要的朋友参考一下 一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致的,有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据。当 Session f
1、一级缓存:指的是mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入sqlSession中,再次查询的时候,先去sqlSession中查询,有的话直接拿出,当sqlSession消失时,mybatis的一级缓存也就消失了,当调用sqlSession的修改、添加、删除、commit()、close()等方法时,会清空一级缓存。 2、二级缓存:指的是mybati
一级缓存是session级别的缓存,默认开启,当查询一次数据库时,对查询结果进行缓存,如果之后的查询在一级缓存中存在,则无需再访问数据库; 二级缓存是sessionFactory级别的缓存,需要配置才会开启。当进行sql语句查询时,先查看一级缓存,如果不存在,访问二级缓存,降低数据库访问压力。
让我澄清一下我对二级缓存的理解。在我的web应用程序的基类中有一个查询。几乎每一个操作都会调用此查询(我使用的是Struts,这就是应用程序的设计方式,因此不会真正弄乱它),例如,加载我的主页会调用三个单独的Struts操作,并为每个操作执行此查询。QueryDsl形式的查询看起来像
本文向大家介绍Hibernate中一级缓存和二级缓存之间的区别,包括了Hibernate中一级缓存和二级缓存之间的区别的使用技巧和注意事项,需要的朋友参考一下 Hibernate支持两种类型的缓存,一种是第一级缓存,另一种是第二级缓存。 一级缓存是会话级缓存,它始终与会话级对象关联。这种类型的缓存用于通过缓存对象的状态来最小化Db交互。 那不是在事务中完成每次修改之后更新,而是仅在事务结束时更新
我正在实现一个基于实体属性值的持久化机制。所有数据库访问都是通过Hibernate完成的。我有一个包含节点路径的表,它非常简单,只有一个id和一个路径(字符串)。路径数量很少,大约几千条。 主表有数百万行,我没有重复路径,而是将路径规范化为它们自己的表。以下是我在插入主表时想要的行为 1)检查路径表中是否存在路径(通过实体管理器查询,使用路径值作为参数) 2) 如果不存在,则插入并获取id(通过实