论坛首页 Java企业应用论坛

关于hibernate3 中bulk delete/update与缓存同步问题

浏览 3410 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-09-01  
   小弟最近刚学hibernate,看的是深入浅出hibernate一书。里面碰到一些关于缓存的问题。
建了个简单的表测试 User 里面的字段只有 id 和 name

其中操作User类中(OperatorUser类)有个删除User的方法和获取User的方法如下
//删除User
          
public void deleteUser(String id){
		Transaction tran = session.beginTransaction() ;
		String hql = "delete User where id=?" ;
		Query q = session.createQuery(hql) ;
		q.setString(0, id) ;
		
		q.executeUpdate() ;
		
		tran.commit() ;
	}

         //获取user
public User getUser(String id){
		Transaction tran = this.session.beginTransaction() ;
		User user = (User) this.session.load(User.class, id) ;
		tran.commit() ;
		
		return user ;
	}
         


写了个测试类Test
       
 OperatorUser op = new OperatorUser() ;
	User user=op.getUser("001") ;
	System.out.println(user.getName()) ;
		
	op.deleteUser("001") ;
		
	User user01= op.getUser("001") ;
	System.out.println(user01.getName()) ;


运行,没错,会打印出相同的姓名。因为当调用deleteUser()方法时,Hibernate的内部缓存和数据库不同步。但是当我注释掉
          
           //System.out.println(user.getName()) ;
          
           //op.deleteUser("001") ;

//User user01= op.getUser("001") ;
//System.out.println(user01.getName()) ;

再重新运行一次下面注释掉一些的代码-----意味着重新打开了一个session,而前面运行那次的session已经关闭,相对应前面的session的缓存也不存在了。
         OperatorUser op = new OperatorUser() ;
User user=op.getUser("001") ;--运行到此时,不会抛出异常,从二级缓存中取出的吗?        //System.out.println(user.getName()) ;---取消注释,运行到此时候,抛出异常,说没有相应的列          
         //op.deleteUser("001") ;

//User user01= op.getUser("001") ;
//System.out.println(user01.getName()) ;

可以,没错,不会抛出异常,但,加上System.out.println(user.getName());时,
却抛出异常,说数据库中没有相应的列!
    问题就在这:为什么调用op.getUser("001")不会抛出异常,为什么调用user.getName()却说没有相应的列!
两次运行,不同的session,内部缓存不同。但是二级缓存相同。也就是说二级缓存里应该有Id 为 001的User实体对象才是。但是为什么调用user.getName()时会抛出异常呢?

通过指点,再在网上查了下关于session.load方法的信息,的确是关于load方法延迟加载的问题,而和缓存没有多大关系,因为两次运行,无论是sessionfactory还是session,两次都不同。

关于session.load():
1. load方法会先从内部缓存和二级缓存中查找实体对象,看看缓存中是否存在该对象。session.get()方法也一样。
2. hibernate中的load方法的加载方式是延迟加载, 返回的是一个实体对象的代理实例,,此时的代理类实例是由运行时动态生成的类,该代理类实例包括原目标对象的所有属性和方法,该代理类实例的属性除了ID不为null外,所在属性为null值,当调用getXXX()方法时,才会真正地到数据库里获得属性值。所以第二次再执行时,会抛出异常!
   发表时间:2008-09-02  
你用的是延时加载,获取PO的时候用的是load()方法,Hibernate中对load()加载方式的处理是,认为"001"这个id对应的对象在数据库中是一定存在的,所以使用代理来延迟加载对象,也就是说当你第二次执行到
User user = op.getUser("001");
的时候,Hibernate并没有去数据库中去取得这个id为"001"的对象,可是第一次你执行测试代码的时候你已经把数据库里的数据删掉了啊,所以第二次再执行到
System.out.println(user.getName());
的时候,就要真正去数据库中取了,然后就会抛出没有相应的列的异常了。

数据库没数据是我估计的,说的不一定对。
1 请登录后投票
   发表时间:2008-09-02  
因为load方法是延时加载,你用get就会马上抛出异常了
1 请登录后投票
   发表时间:2008-09-02  
    恩,谢谢两位的指点,再在网上查了下关于session.load方法的信息,的确是关于load方法延迟加载的问题,而和缓存没有多大关系,因为两次运行,无论是sessionfactory还是session,两次都不同。

     关于session.load():
          1. load方法会先从内部缓存和二级缓存中查找实体对象,看看缓存中是否存在该对象。session.get()方法也一样。
          2. hibernate中的load方法的加载方式是延迟加载, 返回的是一个实体对象的代理实例,,此时的代理类实例是由运行时动态生成的类,该代理类实例包括原目标对象的所有属性和方法,该代理类实例的属性除了ID不为null外,所在属性为null值,当调用getXXX()方法时,才会真正地到数据库里获得属性值。所以第二次再执行时,会抛出异常!

     谢谢两位的指点。
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics