HIbernate事物管理

主要解决的是个例问题:

脏读:一个事务读到另一个事务未提交的内容

       不可重复读:一个事务读到另一个事务已提交的内容(insert)

       虚读(幻读):一个事务读到另一个事务已提交的内容(update)

解决这三个问题的级别:

read uncommittd,读未提交。存在3个问题。

readcommitted,读已提交。解决:脏读。存在2个问题。

repeatableread ,可重复读。解决:脏读、不可重复读。存在1个问题。

serializable,串行化。单事务。没有问题。

乐观锁:

就是再起POJO对象中加一个version字段,表示其版本号,类型是Integer

在*.hbm.xml文件中配置<version name="...">

 

public class Customer {
  private Integer id;
  private String cname;
  //表示客户与订单之间的一对多关系
  private Set<Order> orderSet=new HashSet<Order>();
  private Integer version;

 

<version name="version"></version>

 

hibernate的二级缓存

 

hibernate的二级缓存是SessionFactory级别的缓存。

 

 

hibernate二级缓存操作配置:

 

1.导入jar包:ehcache-1.5.0.jar/commons-logging.jar/ backport-util-concurrent.jar

2.开启二级缓存(我要使用二级缓存)

3.确定二级缓存提供商(我要使用哪个二级缓存)

4.确定需要缓存内容

导入jar包:

ehcache-1.5.0.jar是二级缓存的核心包,commons-logging.jar/和backport-util-concurrent.jar都是其依赖包

开启二级缓存:

<property name="hibernate.cache.use_second_level_cache">true</property>


配置二级缓存提供商:

 <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

 

缓存内容配置:

<!-- 类缓存配置 -->
	<class-cache usage="read-only" class="com.study.hibernate.Customer"/>
	<class-cache usage="read-only" class="com.study.hibernate.Order"/>
	<!--集合缓存设置-->
	<collection-cache usage="read-only" collection="com.study.hibernate.Customer.orderSet"/>


类缓存测试:

 @Test
   public void test8(){
	   Session session=HBUtils.getSession();
		 //开启事物
		Transaction tr =  session.beginTransaction();
		Customer customer1 = (Customer) session.get(Customer.class, 6);
		session.clear();//清楚一级缓存
		Customer customer2 = (Customer) session.get(Customer.class, 6);
		System.out.println(customer1==customer2);
		//提交事物
		tr.commit();
		//关闭会话
		session.close();
   }


上述测试如果打印两次sql语句,那么二级缓存失效,如果打印一次,则二级缓存起作用。

 

测试结果:打印一次     但是比较结果是false

类缓存存储的不是类对象,而是散列码,所以,当有数据要查询的时候,查看二级缓存中有无此数据,如果有,则把该数据组装成对象,然后返回。

集合缓存测试:

@Test
   public void test9(){
	   Session session=HBUtils.getSession();
		 //开启事物
		Transaction tr =  session.beginTransaction();
		Customer customer1 = (Customer) session.get(Customer.class, 6);
		for(Order o:customer1.getOrderSet()){
			System.out.println(o);
		}
		session.clear();//清楚一级缓存
		Customer customer2 = (Customer) session.get(Customer.class, 6);
		for(Order o:customer2.getOrderSet()){
			System.out.println(o);
		}
		//提交事物
		tr.commit();
		//关闭会话
		session.close();
   }


集合缓存存储的不是集合,而是id的值,所以在二级缓存中取数据的时候,是取到的id,然后再去类缓存中去数据。

时间戳测试:

假如我们在一次查询后,更改了其数据库中的数据,那么它是怎么

 

@Test
	public void test10() {
		Session session = HBUtils.getSession();
		// 开启事物
		Transaction tr = session.beginTransaction();
		Customer customer1 = (Customer) session.get(Customer.class, 6);
		System.out.println(customer1.getCname());
		session.createQuery("update Customer set cname=:cname where id=:id")
				.setParameter("cname", "pe").setParameter("id", 6)
				.executeUpdate();
		// 提交事物
		tr.commit();
		// 关闭会话
		session.close();

		Session session1 = HBUtils.getSession();
		// 开启事物
		Transaction tr1 = session1.beginTransaction();
		Customer customer2 = (Customer) session1.get(Customer.class, 6);
		System.out.println(customer2.getCname());
		// 提交事物
		tr1.commit();
		// 关闭会话
		session1.close();
	}

 

查询缓存:

 

查询缓存默认不使用。需要手动开启

查询缓存:将HQL语句与 查询结果进行绑定。通过HQL相同语句可以缓存内容。

默认情况Query对象只将查询结果存放在一级和二级缓存,不从一级或二级缓存获取。

查询缓存就是让Query可以从二级缓存获得内容

要使用查询缓存,则必须开启查询缓存

<!--开启查询缓存  -->
    <property name="hibernate.cache.use_query_cache">true</property>
@Test
	public void test11() {
		Session session = HBUtils.getSession();
		// 开启事物
		Transaction tr = session.beginTransaction();
		Query query=session.createQuery("from Customer");
		query.setCacheable(true);   //从二级缓存中取数据,取不到就查询数据,并且把数据放到二级缓存中
		List<Customer> cusList=query.list();//查询所有的数据
		for(Customer c:cusList){
			System.out.println(c.getCname());
		}
		// 提交事物
		tr.commit();
		// 关闭会话
		session.close();

		Session session1 = HBUtils.getSession();
		// 开启事物
		Transaction tr1 = session1.beginTransaction();
		Query query1=session1.createQuery("select c from Customer c");//不同的hql语句,从二级缓存中获取
		query1.setCacheable(true);
		List<Customer> cusList1=query1.list();//查询所有的数据
		for(Customer c:cusList1){
			System.out.println(c.getCname());
		}
		// 提交事物
		tr1.commit();
		// 关闭会话
		session1.close();
	}

 

测试结果:打印一次语句,可以看到上述的技术hql不同,但转换成的sql语句相同,所以只打印一次。

 

 

所以,查询缓存中根据sql语句判断对否相同。

ehcache文件配置:

在使用二级缓存的时候,可以配置一些参数来优化二级缓存

默认的配置文件:ehcahe-1.5.0.jar//ehcache-failsafe.xml文件中,主要的配置项如下:

 

<defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />

 

 

 

 

我们现在要更改其文件配置,只需在src下创建一个名为ehcache.xml的文件

 

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="D:/ehcache"/> <!-- 二级缓存文件的存放位置 -->
<defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
</ehcache>

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值