выпуск транзакции mybatis-spring - PullRequest
0 голосов
/ 25 мая 2011

У меня проблемы с использованием транзакции CMT Spring с mybatis, у меня есть класс, который использует 2 MapperFactoryBean для вставки записи.

При вставке записей получается исключение ограничения FOREIGN KEY;кажется, что оба работают в разных сеансах, и во втором не удалось найти недавно вставленный идентификатор.

При передаче значения 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.springframework.context.support.ClassPathXmlApplicationContext@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.springframework.beans.factory.support.DefaultListableBeanFactory@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

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

Из журнала отладки похоже, что tx никогда не запускался. Я думаю, проблема в том, что @Transactional не включен по умолчанию. Вам нужно добавить <tx:annotation-driven transaction-manager="transactionManager" /> в ваш XML-файл Spring.

1 голос
/ 25 мая 2011

Не уверен, что это решит проблему, но что-то определенно не так:

<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. Я не могу видеть, чтобы на этот компонент ссылались явно, но это, вероятно, вызывает некоторые проблемы. Каким путем вы хотите пойти, делегировать серверу приложений (вы работаете на реальном сервере приложений или даже используете Tomcat / Jetty?) Или позволить Spring обрабатывать транзакции? Если последнее, удалите директиву для JTA, другой, удалите определениеactionManager (или измените класс на менеджер транзакций JTA).

...