问题描述
我对一个基表查询A a=find("hql").get(0);然后a.setProp(555); 然后对换一个字段查询B b=find("ohterhql").get(0);在第一次查询时没问题在b的find时会将a setProp的值持久化到数据库中这是为什么hibernate不熟,请教各位<property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.format_sql">true</prop><prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop><prop key="hibernate.cache.use_query_cache">true</prop></props></property></bean><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"></property></bean><!-- 支持 @Transactional 标记 --><tx:annotation-driven transaction-manager="transactionManager"proxy-target-class="true" /><!-- =========== openSessionInViewInterceptor ==============--><bean id="openSessionInViewInterceptor"class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"><property name="sessionFactory" ref="sessionFactory" /></bean>hibernate3.2+spring2
解决方案
在那个调用了a.setProp(555); 方法的@Transactional(propagation=Propagation.XXXXXX, readOnly=true)加上readOnly。因为Hibernate有持久状态和脱管状态,持久状态就是Hibernate 的session.close之前(正确来说,是session flush或commit之前),经session 查询出来的对象都是脱管状态。参照Hibernate的文档:引用持久(Persistent) - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行DELETE语句。 假设@Transactional(propagation=Propagation.XXXXXX, [color=red]readOnly=true[/color])public void doSomething(Object a){ ... a.setProp(555); ...}而调用a.setProp(555)的doSomething方法有@Transactional修饰,表示此方法在spring容器包装上事务,也就是代码进入方法之前,spring会启用事务,退出方法的时候会提交事务(等于是调用了flush或者commit),这时候,虽然你没有显式的保存a,但是还是会被持久化的。发生此方法内发生异常的时候,事务则回滚(不保存)readOnly则表示,此方法内对持久对象修改不被保存。
解决方案二:
这个问题只能加入事务处理才可以,设置你的这个方法为read-only就不会出现自动提交之前取出数据又赋值的问题了!楼上说的很详细
解决方案三:
情况没错,建议你在做完a查询,b查询之后再进行对a,b的赋值操作。参考资料http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html#objectstate-flushingsession 刷出数据就会保存到数据库,session什么时候刷出引用 * before some query executions//在某些查询语句执行之前 * from org.hibernate.Transaction.commit() * from Session.flush() The SQL statements are issued in the following order 1. all entity insertions, in the same order the corresponding objects were saved using Session.save() 2. all entity updates 3. all collection deletions 4. all collection element deletions, updates and insertions 5. all collection insertions 6. all entity deletions, in the same order the corresponding objects were deleted using Session.delete()