4

TestCase で @Transactional アノテーションを使用できません。回避策があります-TransactionalManagerを直接使用します。残念ながら、SpringContext の DataSource に基づいて groovy で Sql オブジェクトを作成し、データベースに行を挿入すると、ロールバックしません。

@ContextConfiguration(locations = [ "../dao/impl/ibatis/spring-data-context-config.xml"])
@RunWith(SpringJUnit4ClassRunner.class)
public class OrganizationTest {

@Autowired
DataSource dataSource;

@Autowired
DataSourceTransactionManager transactionManager;

private TransactionStatus transactionStatus;

@Before
public void setUp() {
    transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
}
@After
public void tearDown() {
    transactionManager.rollback(transactionStatus);
    transactionStatus = null;
}


@Test
public void shallObtainSequenceNo() throws Exception {

    Connection connection = dataSource.getConnection();
    connection.setAutoCommit(false);
    Sql sql = new Sql(dataSource);

    //given
    Organization organization = new Organization("KongregatzionIX", "bisut000000000000001");
    //when
    organization.insert(sql);
    //then
    assertNotNull(organization.getId());
    }
}

SQL クエリは次のようになります。

public class Organization {

String name;
String id;
String parentId;

Organization(String name, String parentId){
    this.name = name;
    this.parentId = parentId;
}

public void insert(Sql sql){
    String createdBy = GlobalConstant.SABA_ADMIN_ID.getValue();
    String updatedBy = GlobalConstant.SABA_ADMIN_ID.getValue();
    String companyType = "2";
    String flags = "1000000000";

    id = sql.firstRow( "select 'bisut' || LPAD(TPT_COMPANY_SEQ.NEXTVAL,  15, '0') as id from dual ").id;

    def timeStamp = sql.firstRow("select  to_char(SYSTIMESTAMP, 'YYYYMMDDHH24MISSFF') as ts FROM DUAL ").ts;
    def nameIns = name;
    def today = new java.sql.Date(new Date().getTime());
    sql.executeInsert('''
                INSERT INTO TPT_COMPANY(ID, TIME_STAMP, CREATED_BY, CREATED_ON, UPDATED_BY, UPDATED_ON, CI_NAME, NAME, CI_NAME2, NAME2, COMPANY_TYPE, FLAGS, PARENT_ID)
                VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
                ''' ,
                [id, timeStamp, createdBy, today, updatedBy, today, nameIns.toLowerCase(), nameIns, nameIns.toLowerCase(), nameIns, companyType, flags, parentId]);
 }
}

もちろん、テスト済みのメソッド全体にまたがるトランザクションを設定したいと考えています。

// 編集

評判が小さすぎて答えられませんが、TransactionAwareDataSourceProxy は私が探していたものです。

4

2 に答える 2

0

私が見つけたマットによる回答はうまくいきました。唯一の注意点は、Sql.closeResources(Connection)execute メソッドと query 呼び出しの後に呼び出され、Sql.withTransactionまたは内にいる場合を除き、接続を閉じることですSql.cacheConnection

これが意味することは、確実にトランザクションを認識できるということですが、or内で実行されるクロージャー内でのみです。SpringまたはJEEトランザクション管理が行うことと同様に、Webサービス呼び出しのスレッド全体でトランザクション認識を使用して、WebサービスでDAOを調整しようとしています。Sql.withTransactionSql.cacheConnectiongroovy.sql.Sql

jersey エンドポイントとその下にコンポーネントがある場合、理想的にはトランザクション スコープを DAO レイヤー固有のブロックに限定する必要はありません。これはgroovy.sql.Sqlインスタンスが存在する場所だからです。Sql.withTransactionしたがって、トランザクション認識/ロールバック機能に対する不十分なソリューションに依存していることがわかったのはなぜですか。

参考までに: Github Sql.java ソース たとえばexecuteUpdate、実行後、closeResources接続のクローズのみをスキップする多くのメソッドが呼び出されることに気付くでしょうif (cacheConnection)。したがって、クロージャーブロックを実行することによってのみ、withTransactionまたはcacheTransaction使用できます。これは著者の意図であると私は信じていますcommit()rollback()Web サービス要求のスコープ全体に一致するトランザクションの開始と終了の制限を除けば、これは問題ありません。これは警告であり、私の解決策はcloseResources、このクラスの作成者が寛大にこれをオーバーライド可能にしたため、オーバーライドすることです。トランザクション アクティビティに基づいて接続を閉じないようにオーバーライドします。

つまり、トランザクション管理でこの接続を何らかの方法で処理している場合closeResources、ノーオペレーションで実装します。それ以外の場合は、実装をオーバーライドしないでください。

于 2015-12-11T18:27:49.543 に答える