2017-06-22 11 views
0

DAOクラスのいずれかで、2つの異なるOracleテーブルにレコードを挿入するメソッドがあります。レコードをテーブルの両方に挿入するか、挿入しないかのどちらかにします。@Transactionalとcn.setAutoCommit(false)を使用して複数のテーブルにレコードを挿入することはできません。jdbcTemplate

これを達成するために、私は@Transactionalcn.setAutoCommit(false)コードスニペットの両方を使用しています。

これをテストするために、私は意図的にSQLに間違った列名を入れて、2番目のテーブルのデータ挿入が失敗するようにしました。私の予想は、誤ったクエリのために2番目のテーブルの挿入が失敗したため、最初のテーブルにデータが挿入されないということです。しかし何らかの理由でそれが起こらなかった。レコードはまだ最初のテーブルに挿入されており、2番目のテーブルにはレコードが挿入されていません。

実装がここで間違っていないようです。私がここで何が不足しているか分からない。

EventLogDao.java

@Transactional 
public long saveEventData(EventLog eventLog, String userId) throws SQLException { 
     Connection cn = this.dataSource.getConnection(); 
     cn.setAutoCommit(false); 

     //(FIRST TABLE INSERTION - Table Name: EVENT_LOG) 
     //save data in event log table 
     long eventId = getNextEventIdSequence(); 
     saveEventLogData(eventId, eventLog); 

     //(SECOND TABLE INSERTION - Table Name: EVENT_LOG_MESSAGE) 
     //save data in event log message table 
     saveEventLogMessageData(eventId, eventLog.getEventLogMessage()); 

     cn.commit(); 
     return eventId; 
    } 


private void saveEventLogData(long eventId, EventLog eventLog) { 
     Object[] parameters = {eventId, eventLog.getRouteId(), eventLog.getEventType().getEventTypeId(), 
      eventLog.getOrderId(), eventLog.getIncomingEventTimestamp(), eventLog.getOutgoingEventTimestamp()}; 
     int[] types = {Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP, Types.TIMESTAMP}; 
     int rowsAffected = jdbcTemplate.update(INSERT_EVENT_LOG_SQL2, parameters, types); 
     System.out.println("rowsAffected (eventlog) = " + rowsAffected); 
    } 


private int saveEventLogMessageData(long eventId, EventLogMessage eventLogMessage) { 
     Object[] parameters = {eventId, eventLogMessage.getIncomingEventMessage(), eventLogMessage.getOutgoingEventMessage()}; 
     int[] types = {Types.INTEGER, Types.VARCHAR, Types.VARCHAR}; 
     int rowsAffected = jdbcTemplate.update(INSERT_EVENT_LOG_MESSAGE_SQL2, parameters, types); 
     System.out.println("rowsAffected (eventLogMessage) = " + rowsAffected); 
     return rowsAffected; 
    } 

applicationContext.xmlを

<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> 
     <constructor-arg> 
      <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
       <property name="dataSource" ref="dataSource"/> 
      </bean> 
     </constructor-arg> 
     <property name="propagationBehavior"> 
      <util:constant static-field="org.springframework.transaction.support.DefaultTransactionDefinition.PROPAGATION_REQUIRED"/> 
     </property> 
     <property name="isolationLevel"> 
      <util:constant static-field="org.springframework.transaction.support.DefaultTransactionDefinition.ISOLATION_READ_COMMITTED"/> 
     </property> 
    </bean> 


<bean id="eventLogDao" class="com.ebayenterprise.publicapi.events.dao.EventLogDao"> 
    <constructor-arg ref="dataSource" /> 
</bean> 

案内してください。

+0

私はよく分からないが、私はあなたが1とは別の接続を使用していると思いますトランザクションによって処理された場合、データソースから接続を取得するときに、JTAトランザクションおよびいくつかのラッパーを使用していない限り、この接続はトランザクションに関連付けられません。コンテナとデータベースのトランザクションを区別する必要があります。設定に関する詳細情報を投稿できますか? – karelss

+0

@karelss - これが役立つかどうかはっきりしていませんが、applicationContext設定の元の投稿を更新したばかりです – user2325154

答えて

0

私はあなたが一緒にあなたのjdbcTemplatetransactionTemplateを使用する必要があることとします

public long saveEventData(EventLog eventLog, String userId) throws SQLException { 
     return transactionTemplate.execute(new TransactionCallback<Long>(){ 
     @Override 
     public Long doInTransaction(TransactionStatus transactionStatus) { 
     try { 
      Connection cn = this.dataSource.getConnection(); 
      cn.setAutoCommit(false); 

      //(FIRST TABLE INSERTION - Table Name: EVENT_LOG) 
      //save data in event log table 
      long eventId = getNextEventIdSequence(); 
      saveEventLogData(eventId, eventLog); 

      //(SECOND TABLE INSERTION - Table Name: EVENT_LOG_MESSAGE) 
      //save data in event log message table 
      saveEventLogMessageData(eventId, eventLog.getEventLogMessage()); 

      cn.commit(); 
      return eventId; 
     } catch (Exception e) { 
      transactionStatus.setRollbackOnly(); 
     } 
     return 0; 
    } 

}); 

おそらく、JTAのための構成されていませんし、あなたの@Transactionalは効果がありません。

+0

ありがとう、私はこれを試してみます。 – user2325154

0

TransactionManagerを使用して動作しました。私がコードベースに行った変更は以下に述べられています。

applicationContext.xmlを(更新)

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

    <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> 
     <constructor-arg ref="transactionManager"/> 
     <property name="propagationBehavior"> 
      <util:constant static-field="org.springframework.transaction.support.DefaultTransactionDefinition.PROPAGATION_REQUIRED"/> 
     </property> 
     <property name="isolationLevel"> 
      <util:constant static-field="org.springframework.transaction.support.DefaultTransactionDefinition.ISOLATION_READ_COMMITTED"/> 
     </property> 
    </bean> 

<bean id="eventLogDao" class="com.ebayenterprise.publicapi.events.dao.EventLogDao"> 
    <constructor-arg index="0" ref="dataSource" /> 
    <constructor-arg index="1" ref="transactionManager"/> 
</bean> 

EventLogDao.java(更新)

public EventLogDao(DataSource dataSource, PlatformTransactionManager transactionManager) { 
     super(dataSource, transactionManager); 
    } 

    public long save(EventLog eventLog, String userId) throws Exception { 
     TransactionDefinition txDef = new DefaultTransactionDefinition(); 
     TransactionStatus txStatus = transactionManager.getTransaction(txDef); 
     long eventId = 0L; 
     try { 
      eventId = getNextEventIdSequence(); 
      System.out.println("eventId = " + eventId); 
      saveEventLogData(eventId, eventLog); 
      saveEventLogMessageData(eventId, eventLog.getEventLogMessage()); 
      userId = StringUtils.defaultIfBlank(userId, DEFAULT_USER_ID); 
      saveEventLogAuditData(eventId, userId, eventLog.getOutgoingEventTimestamp()); 
      transactionManager.commit(txStatus); 
     } catch (TransactionException ex) { 
      transactionManager.rollback(txStatus); 
      throw new RuntimeException("Error occurred during tx management in event log tables...", ex); 
     } finally { 
      return eventId; 
     } 
    } 
関連する問題