简体   繁体   English

休眠/春季交易管理问题

[英]Issue with hibernate/Spring transaction management

I am facing a problem with Spring Transaction management. 我在Spring事务管理中面临一个问题。 I am using hibernate as ORM framework. 我正在使用休眠作为ORM框架。 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. 我基本上遵循这里提到的genericDao方法,因此My DaoObject用于获取Domain对象,而服务类具有DAO对象以对其进行处理。

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"). 我已经将服务类标记为@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. 我调试了它,然后知道这是由于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. 我知道Flushmode.never可能无济于事,但在我的应用程序中未看到渗透对象,因此我无法访问它。 is there any other way or some mapping change which can help me ? 还有其他方法或某些映射更改可以帮助我吗?

The issue is with 问题是

if(students== null){ return 0l; }

When Hibernate fetches your entities, they all have null value on the students field. 当Hibernate提取您的实体时,它们在students字段中的值均为空。 At commit time, when checking if they are dirty, getStudents() returns 0, which is different from the value stored in the database. 在提交时,当检查它们是否脏时, getStudents()返回0,这与存储在数据库中的值不同。 So, Hibernate sees them as dirty, and proceeds to the update. 因此,Hibernate认为它们很脏,然后继续进行更新。

If it is suitable to your requirement, changing the type of the student field to the primitive type long instead of Long would probably help. 如果适合您的要求,将student字段的类型更改为基本类型long而不是Long可能会有所帮助。 Note that this would lead to updating all null 's in that column to 0 in the long term. 请注意,从长远来看,这将导致将该列中的所有null都更新为0。

Maybe you should handle that requirement somewhere else, and free the getter from that concern. 也许您应该在其他地方处理该要求,并使吸气剂摆脱这种担忧。

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. 除了XaviLópez的答案外,另一种选择是将Hibernate处理的持久属性与符合您要求的瞬时属性分开。 For example, as follows: 例如,如下:

@Column(name = "students")
public Long getStudentsInternal() {
    return students;
}

@Transient
public Long getStudents() {
    if (students == null) {
        return 0l;
    }
    return students;
}

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): 您还可以通过将注释移动到Hibernate上来配置Hibernate以使用字段而不是属性,这也将解决您的问题(请注意,注释的放置对于实体的所有字段都应是适当的,或者您可以使用@Access来配置排除):

@Column(name = "students")
private Long students;

public Long getStudents() {
    if (students == null) {
        return 0l;
    }
    return students;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM