hibernate / Spring事务管理问题

时间:2011-09-13 15:02:23

标签: java hibernate spring transactions

我正面临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>

我基本上遵循提到here的genericDao方法,因此My DaoObject用于获取Domain对象,而服务类具有DAO对象来处理它们。

我面临的问题:我正在查询大型数据集并将结果加载到服务类内的列表中。我将服务等级标记为@transactional(readonly =“true”)。

处理一些要求我已将盒装原语的所有getter改为

  @Column(name = "students")
public Long getStudents() {
    if(students== null){
        return 0l;
    }
    return this.students;
}

每当我通过命名查询加载所有数据集时。随后会触发多个更新查询以更新数据集。 我调试了它,并且发现因为transaction.commit而发生这种情况。因为hibernate将我的实体视为脏。

有没有办法可以避免这种情况。我知道Flushmode.never可以帮助,但在我的应用程序中,seeion对象没有暴露,所以我无法访问它。有没有其他方法或一些映射改变可以帮助我?

2 个答案:

答案 0 :(得分:2)

问题在于

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

当Hibernate获取您的实体时,它们在students字段上都具有空值。在提交时,检查它们是否脏时,getStudents()返回0,这与存储在数据库中的值不同。因此,Hibernate将它们视为脏,并继续进行更新。

如果它适合您的要求,将student字段的类型更改为基本类型long而不是Long可能会有所帮助。请注意,这会导致长期将该列中的所有null更新为0。

也许你应该在其他地方处理这个要求,并从那个问题中解脱出来。

答案 1 :(得分:2)

除了XaviLópez的答案之外,另一个选择是将Hibernate处理的持久属性与符合您要求的瞬态属性分开。例如,如下:

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

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

您还可以将Hibernate配置为通过移动注释来使用字段而不是属性,它也将解决您的问题(请注意,注释的放置应该适用于实体的所有字段,或者您可以使用{{ 1}}配置排除):

@Access