@Transactionnal + Hibernatetemplate不保存脏对象

时间:2013-10-26 12:56:49

标签: spring hibernate transactional

我已经在论坛中搜索了,我尝试了许多没有成功的事情。

我最后想要一个事务方法,并且只在最后,只保存hibernate对象,我将使用显式 Hibernate getHibernateTemplate ()。 saveOrUpdate()方法,以及 NOT dirty ,我只使用setter进行修改。

阅读我的服务层代码后,我的需求会更加清晰:

为简单起见,我将总结我的代码。

服务层:

@Service("cartService")
public class CartServiceImpl extends AbstractServiceImpl<Cart> implements
        CartService {

   @Autowired 
   private CartDao cartDao;

   @Transactional(readOnly = false)
   public Cart updateCart1(){

            Cart cartA = cartDao.findById(1);
            cartA.setTotal=(5);

            Cart cartB = cartDao.findById(1);
            cartB.setTotal=(5);     
            CartDao.Update(cartB);
   }
}

所以,我需要的是,方法结束时updateCart1()是保存 cartB 的更改,但保存 cartA 的更改。

Dao层:

注意:cartDao的方法(findById,saveOrUpdate)调用HibernateTemplate

public T update(T entite) {
    getHibernateTemplate().saveOrUpdate(entite);
    return entite;
}

public T findById(Serializable id) {
    return getHibernateTemplate().get(this.clazz, id);
}

我不希望Dao的方法在transactionnal服务层方法之外对数据库起作用。我希望它们在服务层上定义的事务结束的数据库中执行。因此,在 hibernate spring 配置文件中:

<prop key="connection.autocommit">false</prop> 

请注意,我使用 OpenSessionInViewFilter 进行Lazyu加载。所以在我的XML文件中:

<filter>
  <filter-name>OpenSessionInViewFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  <init-param>
     <param-name>singleSession</param-name>
     <param-value>false</param-value>
  </init-param> 
</filter>

注意:这些购物车 cartDao的方法在正常情况下正常工作正常。但是我所描述的那个。并且“ @Transactional ”已正确配置并正常工作。

问题:使用此代码,我在数据库中更改了两个对象(cartA和cartB),而我不想修改cartA,我没有明确调用HibernateTemplate的saveOrUpdate方法

论坛中搜索后,我尝试将休眠FLUSH模式设为 FLUSH_NEVER 。但是在执行CartDao.Update(cartB)时,我得到了这个例外:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

拜托,你能帮助我吗?

2 个答案:

答案 0 :(得分:2)

你可以打电话

getHibernateTemplate().getSession().evict(cartA);

将其从会话中删除。

最好的选择是修改cartA。如果您需要使用cartA属性计算某些内容,则可以复制该属性。

答案 1 :(得分:0)

您可以使用org.hibernate.StatelessSession界面代替org.hibernate.Session

在javadocs中,您会看到:

  

无状态会话不实现第一级缓存也不实现交互   使用任何二级缓存,也不实现事务性   后写或自动脏检查,也不进行操作级联   相关实例。无状态会话将忽略集合。   通过无状态会话执行的操作绕过Hibernate的事件模型   和拦截器。无状态会话容易受到数据别名的影响   效果,因为缺少第一级缓存。