2012-03-21 8 views
4

@TransactionAttribute(TransactionAttributeType.REQUIRED)とクラスレベルで注釈を付けたこのEJBを使用すると、トランザクションがコミットされたときにデータがフラッシュされるため、この動作をオーバーライドしない限りすべてのメソッドをトランザクションで実行する必要があります。 、 右?ここまでは順調ですね。 これでpublic User find(String email)メソッドがあり、@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)というアノテーションが付いています。このメソッドはトランザクションでは実行されないため、データを取得するだけです。EJBのJTAを理解する:フラッシングしない

私は自分のアプリケーションをテストしていますが、ejbを使用していくつかのエンティティを作成し、findメソッドを使って1つを取得するブートメソッドがあります。 私の意見では、

- >私はトランザクションで実行されるsave(User u)を呼び出してエンティティ1を作成します。コミットすると、データがフラッシュされます。

- >この手順をもう2つのエンティティで繰り返します。トランザクションがコミットされると、データはフラッシュされます。

- >この時点で私のL2キャッシュ(Eclipselinkを使用)とデータベースに3つのエンティティが必要です。

- >私はfind(String email)メソッドを呼び出します。エンティティを見つけて返します。例外もなく、コードもうまく実行されます。私は興奮し、ビールを開きます。私はstackoverflowで質問する必要はありません。 - >私はすべての3つのエンティティを作成

:実際に何が起こる

。例外なし。

- >私はfind(String email)メソッドを呼び出しますが、エンティティが見つからないためにEjbExceptionが発生します。デバッグこのメソッドが呼び出されたときにデータベースが空であり、データがフラッシュされません私がエンティティを明示的に作成するときには、flushメソッドを呼び出します。これは必須ではありません)。 EJbExceptionがスローされ、コードが停止し、データベースが再度チェックされ、エンティティがそこにあるかどうかが確認されます。そこには例外がスローされます。 findメソッドから@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)を削除すると、トランザクション内で検索が実行されますが、私のコードが機能します。

- >私はビールを開けません。

今、真剣に、何が起こっているのですか?トランザクション内のエンティティを検索する必要があるのはなぜですか?それ以外の場合は、何もフラッシュしません。

EDIT:永続単位:私は検索時にキャッシュがデータベースにフラッシュされ、その後何の実体は、見つかっていないことを言って1以外上げ

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="TribunalExpedientes" transaction-type="JTA"> 
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
    <jta-data-source>tribunalexpedientes</jta-data-source> 
    <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    <shared-cache-mode>ALL</shared-cache-mode> 
    <properties> 
     <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> 
    </properties> 
    </persistence-unit> 
</persistence> 

も例外。

答えて

3

私はあなたが正しく構成されていないと考えています。 persistence.xmlと使用しているアプリケーションサーバーとデータベースを含めます。

JTAまたはRESOURCE_LOCALを使用している場合は、JTAを使用している必要があり、ターゲットサーバをpersistence.xmlに設定する必要があります。

エラーを確認する。エラーが発生した場合、トランザクションはロールバックされます。

NOT_SUPPORTEDは一般的には良い考えではありません。つまり、トランザクションでこのメソッドが呼び出されると例外がスローされます。それは何が起こっているかもしれない。

+0

「NEVER」属性である場合、NOT_SUPPORTEDはトランザクション(アクティブな場合)を中断し、アクティブでない場合はトランザクション外でメソッドを実行します。メソッドを非トランザクションにします。メソッドがトランザクション内で呼び出された場合、例外は発生しません。 – arg20

+1

代わりにNEVERを使用すると、例外が発生しますか? – Chris

+0

@Chris私は例外を得るはいはい!それは言う: 'javax.ejb.EJBException:EJBはグローバルトランザクションで呼び出すことはできません '、そうです、トランザクションはコミットされず、"グローバル "トランザクションが開始されました。どうして?これはある種の最適化ですか?私はRequestScoped CDI Beanから呼び出しています。Beanはトランザクションではありません。私は何が起こっているのか分からない – arg20

1

文が実行されたとき、およびトランザクションがコミットするときに表示されます。 NOT_SUPPORTEDはトランザクションを中断するので、以前のトランザクションがコミットされている場合にのみ、データを見つけることができます。 saveメソッドが停止しているより大きなトランザクションにラップされる可能性があります。このデータはまだトランザクション的に分離されているため、Flushはこれを変更しません。

完了時にコミットされる独自のトランザクションに保存メソッドを入れるには、REQUIRES_NEWを使用してください。

0

トランザクションをコミットしても、Eclipselinkはデータをフラッシュする必要はありません。それが理由。これは私の意見では本当に醜い振る舞いです。 Eclipselinkは、データを実行したいときにそのデータをフラッシュできます。私はそれにもいくつか問題がありました。例えば。 @PrePersistまたは@PreUpdateを使用するときは、トランザクションをコミットするときに発生することが保証されていません。例えば。いくつかの統計を計算する際、Eclipselinkはトランザクションがすでに完了したときに処理を実行できるため、同じトランザクション内で統計を使用することはできません。

em.persist()を作成するために使用するエンティティを使用する必要があります。 dbクエリを実行する場合クエリーが正しくない可能性があるため、Eclipselinkはエンティティをフラッシュするために必要です。しかし、代わりにem.flush()を使用すると、アプリケーションの規模を拡大しようとすると実際には醜いパフォーマンス上の問題が発生します。

関連する問題