我有一个遗留的网络应用程序,我正在维护。它最初是Java1.4,但我已经将其编译为Java5。我们正在使用Spring+Hibernate。我还没有使用注解。我现在还是坚持XDoclet。在它中,我有一个对象图,如下所示:
工作1:m业务1:m活动1:m交易
这些事务不是J2EE事务。我们只是记录从一个活动到另一个活动的工作流程。
在HttpRequest#1中,我更新了几个活动并创建了一个新事务。然后在HttpRequest#2中,我重新显示整个作业。现在我看到的是通常用于作业、操作和活动的SELECT语句,但是接下来我看到了一些用于事务的更新语句。事实证明,这些更新正在将事务恢复到以前的状态,从而丢弃最新的更新。
为什么Hibernate要这么做?
根据请求,下面是.hbm.xml文件:
<hibernate-mapping>
<class name="ActivityTransaction" table="imed_if_move_transactions"
lazy="false" mutable="true">
<cache usage="nonstrict-read-write" />
<id name="id" column="IF_MOVE_TRANSACTION_ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">IMED_IF_MOVE_TRANSACTIONS_S</param>
</generator>
</id>
<property name="activityActionKey" type="java.lang.String"
update="true" insert="true" column="ACTIVITY_ACTION_KEY" />
<property name="approvalStatus" type="int" update="true"
insert="true" column="APPROVAL_STATUS" />
<property name="authorizedBy" type="java.lang.Long" update="true"
insert="true" column="AUTHORIZATION_ID" />
<many-to-one name="authorizedByUser"
class="UserModel" cascade="none"
outer-join="false" update="false" insert="false" not-found="ignore"
fetch="select" column="AUTHORIZATION_ID" />
<property name="date" type="java.util.Date" update="true"
insert="true" column="JOA_TRANSACTION_DATE" />
<many-to-one name="from"
class="JobOpActivity" cascade="none"
outer-join="false" update="true" insert="true" fetch="select"
column="FM_JOB_OP_ACTIVITY_ID" />
<property name="fromIntraActivityStepType" type="java.lang.Integer"
update="true" insert="true" column="FM_INTRAACTIVITY_STEP_TYPE" />
<property name="fromIntraOperationStepType" type="java.lang.Integer"
update="true" insert="true" column="FM_INTRAOPERATION_STEP_TYPE" />
<property name="fromOperationSeqNum" type="java.lang.Integer"
update="true" insert="true" column="FM_OPERATION_SEQ_NUM" />
<many-to-one name="job" class="Job"
cascade="none" outer-join="false" update="true" insert="true" fetch="select"
column="WIP_ENTITY_ID" />
<property name="operationEndDate" type="java.util.Date"
update="true" insert="true" column="OP_END_DATE" />
<property name="operationStartDate" type="java.util.Date"
update="true" insert="true" column="OP_START_DATE" />
<many-to-one name="organization" class="Organization"
cascade="none" outer-join="false" update="true" insert="true" fetch="select"
column="ORGANIZATION_ID" />
<property name="processingStatus" type="java.lang.String"
update="true" insert="true" column="PROCESS_FLAG" />
<property name="quantity" type="int" update="true" insert="true"
column="TRANSACTION_QUANTITY" />
<property name="reasonId" type="java.lang.Long" update="true"
insert="true" column="REASON_ID" />
<property name="reference" type="java.lang.String" update="true"
insert="true" column="REFERENCE" />
<property name="scrapAccountId" type="java.lang.Long" update="true"
insert="true" column="SCRAP_ACCOUNT_ID" />
<property name="spsaId" type="java.lang.Long" update="true"
insert="true" column="SPSA_ID" />
<many-to-one name="to"
class="JobOpActivity" cascade="none"
outer-join="false" update="true" insert="true" fetch="select"
column="TO_JOB_OP_ACTIVITY_ID" />
<property name="toIntraActivityStepType" type="java.lang.Integer"
update="true" insert="true" column="TO_INTRAACTIVITY_STEP_TYPE" />
<property name="toIntraOperationStepType" type="java.lang.Integer"
update="true" insert="true" column="TO_INTRAOPERATION_STEP_TYPE" />
<property name="toOperationSeqNum" type="java.lang.Integer"
update="true" insert="true" column="TO_OPERATION_SEQ_NUM" />
<property name="typeId" type="java.lang.Long" update="true"
insert="true" column="TRANSACTION_TYPE_ID" />
<property name="webKeyEntryId" type="java.lang.String"
update="true" insert="true" column="WEB_KEY_ENTRY_ID" />
<property name="issueMaterial" type="true_false" update="true"
insert="true" column="MATERIAL_ISSUE" />
<property name="createDate" type="java.util.Date" update="true"
insert="true" column="CREATION_DATE" />
<property name="createdBy" type="java.lang.Integer" update="true"
insert="true" column="CREATED_BY" />
<property name="lastUpdateDate" type="java.util.Date" update="true"
insert="true" column="LAST_UPDATE_DATE" />
<property name="lastUpdatedBy" type="java.lang.Integer"
update="true" insert="true" column="LAST_UPDATED_BY" />
</class>
</hibernate-mapping>下面是一个事务设置示例:
<bean id="moldingActivitiesService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="etrack2ProviderTransactionManager"/>
<property name="target" ref="moldingActivitiesServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>发布于 2011-08-11 19:34:53
好了,终于找到问题了。这里有一个更完整的流程:
我有Controller C1、Manager M1、Manager M2和Persister P1。正如我前面所述,M1和M2使用TransactionProxyFactoryBean管理事务。
方法A()调用M1.methodB(),后者调用P1.methodC()
看到问题了吗?
当M1.methodD调用M1.methodE()时,就会发生这种情况。我认为发生的情况是,由于M1和M2都是事务管理的,因此创建了两个事务,每个调用一个事务。这两项交易都是为了争夺系统的真实状态,而这两个交易都没有一个真正的赢家。
发布于 2011-08-04 19:18:59
来自Google http://ajava.org/online/hibernate3api/org/hibernate/FlushMode.html上的Hibernate Javadoc文档
汽车
public static final FlushMode AUTO 有时会在执行查询之前刷新会话,以确保查询永远不会返回陈旧状态。这是默认的刷新模式。
您在JPA管理的实体上所做的每一项修改都是在持久上下文中完成的。这意味着Hibernate假设您在实体中修改的内容是安全的。因此,当您从同一个实体或相关实体中选择数据时,Hibernate将更改的一致性置于其他所有内容之上。因此,它会刷新,然后执行读取,以正确地反映您的更改。如果你不想有这种行为,你可以做两件事:
编辑:关于如何在不使用注释的情况下最好地使用Spring的PlatformTransactionManager,我建议使用TransactionTemplate:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/transaction.html#tx-prog-template将您的PlatformTransactionManager (Hibernate)注入到那里,并使用它从事务处理中抽象出来。
发布于 2011-08-04 18:27:03
取决于您的FLUSHMODE,您将看到这一点,因为每当您执行查询时,hibernate通常都会猜测它是否应该刷新以获得干净和一致的读取。
https://stackoverflow.com/questions/6946361
复制相似问题