hibernate/Spring 事务管理问题
我面临 Spring 事务管理的问题。我使用 hibernate 作为 ORM 框架。下面是我的事务管理弹簧。
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="abstractDao"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true" lazy-init="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
<property name="postInterceptors">
<list>
<ref bean="finderIntroductionAdvisor"/>
</list>
</property>
</bean>
<bean id="abstractService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true" lazy-init="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
我基本上遵循这里提到的 genericDao 方法,所以我的DaoObject 用于获取域对象,服务类具有 DAO 对象来操纵它们。
我面临的问题:我正在查询大型数据集并将结果加载到服务类内的列表中。我已将服务类标记为@transactional(readonly ="true")。
为了处理一些需求,我已经将盒装原语的所有 getter 更改为
@Column(name = "students")
public Long getStudents() {
if(students== null){
return 0l;
}
return this.students;
}
每当我通过命名查询加载所有数据集时。随后会触发多个更新查询来更新数据集。 我对此进行了调试,发现这是由于 transaction.commit 导致的。因为休眠将我的实体视为脏的。
有什么办法可以避免这种情况吗?我知道 Flushmode.never 可能有帮助,但在我的应用程序中,seesion 对象没有公开,所以我无权访问它。有没有其他方法或一些映射更改可以帮助我?
I am facing a problem with Spring Transaction management. I am using hibernate as ORM framework. And below is my spring for transaction management.
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="abstractDao"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true" lazy-init="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
<property name="postInterceptors">
<list>
<ref bean="finderIntroductionAdvisor"/>
</list>
</property>
</bean>
<bean id="abstractService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true" lazy-init="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
I am basically following genericDao approach as mentioned here so My DaoObject are used to fetch the Domain objects and service classes have DAO objects to maipulate them.
issue i am facing : i am querying a large dataset and loading the result in a list inside the service class. i have marked service class as @transactional(readonly ="true").
to handle some reuirement i have changed all the getters of boxed primitive to
@Column(name = "students")
public Long getStudents() {
if(students== null){
return 0l;
}
return this.students;
}
whenever i load all the dataset via a named query. multiple update queries are fired subsequently to update the dataset.
I debugged that and came to know that this is occuring because of transaction.commit. as hibernate is treating my entities as dirty.
is there a way i can avoid this . i know Flushmode.never could be of help but in my application seesion object is not exposed so i do not have access to it. is there any other way or some mapping change which can help me ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除了 Xavi López 的答案之外,另一种选择是将 Hibernate 处理的持久属性与符合您要求的瞬态属性分开。例如,如下所示:
您还可以通过将注释移动到 Hibernate 来配置 Hibernate 使用字段而不是属性,它也可以解决您的问题(注意注释的放置应该与实体的所有字段保持一致,或者您可以使用
@Access
配置排除):In addition to Xavi López's answer, another option is to separate persistent property handled by Hibernate from the transient property that conform to your requirement. For example, as follows:
You can also configure Hibernate to use fields instead of properties by moving annotations to them, it will solve your problem as well (note that the placement of annotations should be consitent for all fields of the entity, or you can use
@Access
to configure an exclusion):问题在于
if(students== null){
返回0l;
}
当 Hibernate 获取您的实体时,它们的
students
字段上都有空值。在提交时,当检查它们是否脏时,getStudents()
返回 0,这与数据库中存储的值不同。因此,Hibernate 认为它们是脏的,并继续更新。如果适合您的要求,将
student
字段的类型更改为原始类型long
而不是Long
可能会有所帮助。请注意,从长远来看,这将导致该列中的所有null
更新为 0。也许您应该在其他地方处理该要求,并将吸气剂从这种担忧中解放出来。
The issue is with
if(students== null){
return 0l;
}
When Hibernate fetches your entities, they all have null value on the
students
field. At commit time, when checking if they are dirty,getStudents()
returns 0, which is different from the value stored in the database. So, Hibernate sees them as dirty, and proceeds to the update.If it is suitable to your requirement, changing the type of the
student
field to the primitive typelong
instead ofLong
would probably help. Note that this would lead to updating allnull
's in that column to 0 in the long term.Maybe you should handle that requirement somewhere else, and free the getter from that concern.