2

Spring(v 3.1)WebアプリケーションでscalaでプログラムされたBeanを使用しようとしましたが、トランザクションに関して奇妙な問題が発生しました。

問題を示すために、Rooで小さいながらも完全なSpringアプリケーションをセットアップしました。正直なところ、なぜ機能しないのかわかりません...

project --topLevelPackage com.app
jpa setup --provider ECLIPSELINK --database DERBY_EMBEDDED
entity jpa --class com.app.MyEntity
field string --fieldName title

次に、Javaでインターフェイスを作成しました

package com.app;
public interface IScalaMainClass {
 void doSomething();
}

package com.app;
public interface IScala1 {
 void someMethod();
}

package com.app;
public interface IScala2 {
 void someMethod();
}

実装はScalaで作成され、Scala1はMyEntityを永続化し、Scala2はDELETEクエリを実行します。

package com.app

import org.springframework.transaction.annotation.Transactional
import org.springframework.stereotype.Repository
import org.springframework.beans.factory.annotation.Autowired

@Repository class ScalaMainClass extends com.app.IScalaMainClass {
 @Autowired var bean1: IScala1 = null
 @Autowired var bean2: IScala2 = null

 @Transactional def doSomething() = {
  bean1.someMethod()
  bean2.someMethod()
 }
}


package com.app

import org.springframework.stereotype.Repository
import javax.persistence.{EntityManager, PersistenceContext}

@Repository class Scala1 extends com.app.IScala1 {
 @PersistenceContext var em: EntityManager = null

 def someMethod = {
  val e = new MyEntity
  em persist e
 }
}


package com.app

import org.springframework.transaction.annotation.Transactional
import org.springframework.stereotype.Repository
import javax.persistence.{EntityManager, PersistenceContext}

@Repository class Scala2 extends com.app.IScala2 {
 @PersistenceContext var em: EntityManager = null

 @Transactional def someMethod = {
  val q = em createQuery "DELETE FROM MyEntity"
  q executeUpdate
 }

}

最後に、IScalaMainClassを実行するJavaのテストが作成されます。

import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.annotation.Rollback;
import org.springframework.beans.factory.annotation.Autowired;

import org.junit.runner.RunWith;
import org.junit.Test;
import org.junit.Assert;

import com.app.IScalaMainClass;

@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback = false)
public class AppTest {
 @Autowired private IScalaMainClass smc;

 @Test public void testIt() {
  smc.doSomething();
 }
}

ここでscalaの依存関係をpom.xmlに追加し、「mvn test」を実行すると、次のようになります。

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active
...
4

2 に答える 2

2

トランザクションおよびその他のアスペクト指向機能のSpringサポートを検討するときは、非常に注意する必要があります。

  • 不変フィールドの自動配線はできません。自動配線は初期化後に依存関係を設定するパターンであり、valは初期化後に変更できない不変のプロパティです。

  • ドキュメントで読むことができるように、Spring AOPサポートはバイトコードウィービングに基づいておらず、純粋にJavaで実装されています:http ://static.springsource.org/spring/docs/3.0.x/reference/aop.html

これは、SpringIoCを介して作成されたBeanのみがSpringAOPサポートの恩恵を受けることができることを意味します。

この章の紹介を見ると、次のように読むことができます。

AOPはSpringFrameworkで次の目的で使用されます...

...特にEJB宣言型サービスの代わりとして、宣言型エンタープライズサービスを提供します。このようなサービスで最も重要なのは、宣言型トランザクション管理です。

したがって、BeanがSpringを介して作成されていない場合、Springトランザクションサポートは利用できません。

于 2012-07-10T12:22:43.433 に答える
1

@ Edmondo1984の答えにはほとんど同意しますが、上記のrainerhのコードはすべてのBeanをSpringコンテキストに配置しているため、Spring Transactionで機能すると思います。

上記のコードから、テストを次のように変更する必要があると思います

@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
public class AppTest extends AbstractTransactionalJUnit4SpringContextTests {
 @Autowired private IScalaMainClass smc;

 @Test public void testIt() {
  smc.doSomething();
 }
}

インポートすることを忘れないでくださいorg.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests

于 2014-01-15T07:50:02.040 に答える