2011-05-25 64 views
0

我有使用CMT Spring事務與mybatis的問題,我有一個使用2 MapperFactoryBean插入記錄的類。mybatis-spring事務問題

插入記錄獲取FOREIGN KEY約束異常時;它似乎都在不同的會話中運行,第二個無法找到新插入的ID。

在第二條記錄的外鍵中傳遞null時;沒有異常被拋出,但事務也沒有被提交。

如果引發任何異常,回滾工作正常。

這裏是我的配置

<tx:jta-transaction-manager /> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">   
    <property name="url" value="${database.url}"/> 
    <property name="driverClassName" value="${database.driverClassName}"/> 
    <property name="username" value="${database.username}"/> 
    <property name="password" value="${database.password}"/> 
    <property name="defaultAutoCommit" value="false" /> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="nestedTransactionAllowed" value="true" /> 
    <property name="validateExistingTransaction" value="true" /> 
    </bean> 

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" />    
    <property name="configLocation" value="classpath:dataAccess-config.xml"/> 
    </bean> 

    <bean id="taskRecordMapper" class="org.mybatis.spring.MapperFactoryBean">  
    <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
    <property name="mapperInterface" value="TaskRecordMapper"/> 
    </bean> 

    <bean id="taskTagRecordMapper" class="org.mybatis.spring.MapperFactoryBean">  
    <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
    <property name="mapperInterface" value="TaskTagRecordMapper"/> 
    </bean> 

代碼片斷在期待

這裏

@Transactional(propagation= Propagation.REQUIRED) 
    public boolean assignTask(Object source, TaskType taskType, String description, 
           long assignedTo, long createdBy, long escalationId, 
           boolean isAssignedToGroup, long parentTaskId, 
           Date deadline, TaskPriority taskPriority) throws Exception 
    { 

    EntityType entityType = TaskUtil.getEntityType(source); 
    long entityId = TaskUtil.getIdFromObject(source); 

    TaskRecord newTask = new TaskRecord(); 

    newTask.setAssignedTo((isAssignedToGroup) ? null : assignedTo); 
    newTask.setCategory(entityType.toString()); 
    newTask.setCreatedBy(createdBy); 
    newTask.setCreatedOn(new Date()); 
    newTask.setDeadline(deadline); 
    newTask.setDescription(description); 
    newTask.setEntityId(entityId); 
    newTask.setEscalationId(escalationId); 
    newTask.setIsAssignedToGroup(isAssignedToGroup); 
    newTask.setIsDeleted(false); 
    newTask.setModifiedBy(null); 
    newTask.setModifiedOn(null); 
    newTask.setOwner(createdBy); 
    newTask.setParentId((parentTaskId == 0) ? null : parentTaskId); 
    newTask.setPriority(taskPriority.toString()); 
    newTask.setReferenceNo(null); 
    newTask.setResult(null); 
    newTask.setStatus(TaskStatus.InProgress.toString()); 
    newTask.setType(taskType.toString()); 

    boolean rValue = taskRecordMapper.insert(newTask) > 0; 


    if(rValue && isAssignedToGroup) 
    { 
     TaskTagRecord tag = new TaskTagRecord(); 

     tag.setTaskId(newTask.getId()); 
     tag.setName("RoleId"); 
     tag.setValue(String.valueOf(assignedTo)); 

     rValue = taskTagRecordMapper.insert(tag) > 0; 
    } 


    return rValue; 
    } 

由於是堆棧跟蹤

org.springframework.dao.DataIntegrityViolationException: SqlSession operation; SQL []; The INSERT statement conflicted with the FOREIGN KEY constraint "FK_task_tag_task". The conflict occurred in database "TEMP", table "dbo.task", column 'id'.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_task_tag_task". The conflict occurred in database "TEMP", table "dbo.task", column 'id'. 
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
    at org.mybatis.spring.SqlSessionTemplate.wrapException(SqlSessionTemplate.java:364) 
    at org.mybatis.spring.SqlSessionTemplate$7$1.doInSqlSession(SqlSessionTemplate.java:344) 
    at org.mybatis.spring.SqlSessionTemplate.execute(SqlSessionTemplate.java:173) 
    at org.mybatis.spring.SqlSessionTemplate.execute(SqlSessionTemplate.java:155) 
    at org.mybatis.spring.SqlSessionTemplate$7.invoke(SqlSessionTemplate.java:339) 
    at $Proxy18.insert(Unknown Source) 
    at com.task.service.TaskService.assignTask(TaskService.java:184) 
    at com.task.service.TaskService.assignTask(TaskService.java:137) 
    at com.core.mapper.TaskServiceTest.main(TaskServiceTest.java:38) 
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_task_tag_task". The conflict occurred in database "TEMP", table "dbo._task", column 'id'. 
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1454) 
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:388) 
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:338) 
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4026) 
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1416) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:185) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:160) 
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:320) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:169) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:45) 
    at $Proxy38.execute(Unknown Source) 
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:22) 
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:51) 
    at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:29) 
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:75) 
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:43) 
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:118) 
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:107) 
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:56) 
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:38) 
    at $Proxy18.insert(Unknown Source) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.mybatis.spring.SqlSessionTemplate$7$1.doInSqlSession(SqlSessionTemplate.java:342) 
    ... 7 more 

這裏是調試日誌

02:41:32,465 INFO main [ClassPathXmlApplicationContext] Refreshing org[email protected]1bc887b: startup date [Thu May 26 02:41:32 GST 2011]; root of context hierarchy 
02:41:32,512 INFO main [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [dataAccessApplicationContext.xml] 
02:41:33,034 INFO main [DefaultListableBeanFactory] Pre-instantiating singletons in org.s[email protected]173b262: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,org.springframework.context.config.internalBeanConfigurerAspect,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.beans.factory.config.PropertyOverrideConfigurer#0,dataSource,transactionManager,sqlSessionFactory,managedTransactionFactory,springApplicationContext]; root of factory hierarchy 
02:41:34,512 DEBUG main [Connection] ooo Connection Opened 
02:41:34,659 DEBUG main [PreparedStatement] ==> Executing: select id, order_number, com_id, order_date, status, source, created_on, created_by, is_deleted, modified_on, modified_by from order WHERE (id = ? and is_deleted = ?) 
02:41:34,660 DEBUG main [PreparedStatement] ==> Parameters: 264(Long), false(Boolean) 
02:41:34,699 DEBUG main [ResultSet] <== Columns: id, order_number, com_id, order_date, status, source, created_on, created_by, is_deleted, modified_on, modified_by 
02:41:34,709 DEBUG main [ResultSet] <==  Row: 264, 00277-100410, 1041, 2010-01-01 00:00:00.0, Pending, COMPANY A, 2011-05-24 00:21:00.337, 1, 0, null, null 
02:41:34,723 DEBUG main [Connection] xxx Connection Closed 
02:41:34,742 DEBUG main [Connection] ooo Connection Opened 
02:41:34,747 DEBUG main [PreparedStatement] ==> Executing: insert into task (type, status, owner, description, context_id, deadline, assigned_to, parent_id, priority, escalation_id, reference_no, result, created_on, created_by, modified_on, modified_by, category, entity_id, is_deleted, is_assigned_to_group) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
02:41:34,747 DEBUG main [PreparedStatement] ==> Parameters: Investigation(String), InProgress(String), 1(Long), Please investigate this order(String), null, 2011-05-27 02:41:34.736(Timestamp), null, null, Normal(String), 1(Long), null, null, 2011-05-26 02:41:34.737(Timestamp), 1(Long), null, null, Order(String), 264(Long), false(Boolean), true(Boolean) 
02:41:34,757 DEBUG main [PreparedStatement] ==> Executing: select @@identity 
02:41:34,757 DEBUG main [PreparedStatement] ==> Parameters: 
02:41:34,763 DEBUG main [ResultSet] <== Columns: 
02:41:34,763 DEBUG main [ResultSet] <==  Row: 94 
02:41:34,782 DEBUG main [Connection] xxx Connection Closed 
02:41:34,800 DEBUG main [Connection] ooo Connection Opened 
02:41:34,803 DEBUG main [PreparedStatement] ==> Executing: insert into task_tag (name, value, task_id) values (?, ?, ?) 
02:41:34,804 DEBUG main [PreparedStatement] ==> Parameters: RoleId(String), 1(String), 94(Long) 
02:41:34,842 INFO main [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml] 
02:41:34,859 INFO main [SQLErrorCodesFactory] SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase] 
02:41:34,944 DEBUG main [Connection] xxx Connection Closed 
+0

您可以在以下類上啓用'DEBUG'日誌並重新運行:org.springframework.orm,org.springframework.jdbc&java.sql。請發佈日誌輸出。 – AngerClown 2011-05-25 15:58:12

+0

感謝AngerClown的迴應;張貼日誌輸出; – Danish 2011-05-25 22:56:36

回答

2

從DEBUG日誌中,它看起來像一個tx從未開始。我認爲問題是@Transactional默認情況下未啓用。您需要將<tx:annotation-driven transaction-manager="transactionManager" />添加到您的Spring xml文件中。

+0

是的AngerClown,在添加註釋驅動標記事務啓動後,但我在我的代碼也有問題,特別是方法拋出異常,因爲沒有觸發回滾,一旦我改變我的方法提交和回滾正常工作。謝謝你們幫助我。 – Danish 2011-05-26 10:40:19

+0

@Danish你如何改變它?我有同樣的問題 :( – 2014-05-30 14:21:05

1

不知道,這將解決這個問題,但事情肯定是不對的:

<tx:jta-transaction-manager/> 

這意味着你在委託交易使用JTA,作爲處理的應用服務器。 而且你也有

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
<property name="dataSource" ref="dataSource"/> 
<property name="nestedTransactionAllowed" value="true" /> 
<property name="validateExistingTransaction" value="true" /> 
</bean> 

這意味着你正在使用Spring事務處理。我看不到這個bean被顯式引用,但可能會導致一些問題。你想以什麼方式,委託給應用服務器(你甚至在真正的應用服務器上運行,還是使用Tomcat/Jetty?),還是讓Spring處理事務?如果是後者,則將指令移除到另一個JTA,移除transactionManager定義(或將類更改爲JTA事務管理器)。

+0

感謝abalogh您的回覆。我希望Spring處理事務,我從配置中刪除了;之後測試了上面提到的場景,仍然得到相同的結果 – Danish 2011-05-25 12:07:30

+0

你可以發佈你的stacktrace嗎? – abalogh 2011-05-25 12:29:26

+0

發佈堆棧跟蹤。謝謝 – Danish 2011-05-25 13:04:35