开发者

Issue with hibernate/Spring transaction management

开发者 https://www.devze.com 2023-04-04 09:07 出处:网络
I am facing a problem with Spring Transaction management. I am using hibernate as ORM framework. And below is my spring for transaction management.

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.Tr开发者_如何学JAVAansactionProxyFactoryBean" 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 ?


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:

@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):

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

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


The issue is with

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

When Hibernate fetches your entities, they all have null value on the studentsfield. 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 studentfield to the primitive type long instead of Long would probably help. Note that this would lead to updating all null'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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号