openjpa2.0 は実行時にエンティティをどのように強化しますか?
質問
以下は私のテストコードです:
package jee.jpa2;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test
public class Tester {
EntityManager em;
EntityTransaction tx;
EntityManagerFactory emf;
@BeforeClass
public void setup() {
emf = Persistence.createEntityManagerFactory("basicPU", System.getProperties());
}
@Test
public void insert() {
Item item = new Item();
for (int i = 0; i < 1000; ++i) {
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
item.setId(null);
em.persist(item);
tx.commit();
em.clear();
em.close();
tx=null;
em=null;
}
}
@Test
public void read() {
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
Query findAll = em.createNamedQuery("findAll");
List<Item> all = findAll.getResultList();
for (Item item : all) {
System.out.println(item);
}
tx.commit();
}
}
そして、これがエンティティです:
package jee.jpa2;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
@Entity
@NamedQuery(name="findAll", query="SELECT i FROM Item i")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false, updatable= false)
protected Long id;
protected String name;
public Item() {
name = "Digambar";
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return String.format("Item [id=%s, name=%s]", id, name);
}
}
テストを実行するとエラーが発生します:
Item [id=1, name=Digambar]
Item [id=2, name=Digambar]
PASSED: read
FAILED: insert
<openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.EntityExistsException: Attempt to persist detached object "jee.jpa2.Item-2". If this is a new instance, make sure any version and/or auto-generated primary key fields are null/default when persisting.
FailedObject: jee.jpa2.Item-2
at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2563)
at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2423)
at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1069)
at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:705)
at jee.jpa2.Tester.insert(Tester.java:33)
ここで何が起こっているのか説明してください。
解決
厳格に答タイトル、実行時の補完であることjavaagentできる動的にロードされる利用の場合は、JDK1.6(これは記録され 企業強化).
に関する問題だ、疑いをもってOpenJPAバなどの見数 類似の そうした問題に OPENJPA-755のエラーメッセージはインコヒーレントとのコードからだの設定に主キーのフィールドへ null
といバージョンです。きます。
もっとも、手軽に行うことができる"の回避"の発行する新しい Item
インスタンス内のループを実行します。のようなこと:
public void insert() {
for (int i = 0; i < 1000; ++i) {
Item item = new Item();
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
em.persist(item);
tx.commit();
em.clear();
em.close();
tx=null;
em=null;
}
}
その他の注意点
なぜ通 System.getProperties()
作成時に EntityManagerFactory
?
べきであり、 EntityManagerFactory
期末試験:
@AfterClass
public static void closeEntityManagerFactory() {
emf.close();
}
更新: 回答を掲載しています。からJPA仕様:
3.2体のインスタンスのライフサイクル
この章では EntityManager業務の管理 企業インスタンスのライフサイクルになっています。An 企業のインスタンスができるのが特徴 として、これを管理し、一戸建て、 削除されます。
- A 新しい entityインスタンスは 無根強い人, はな 連続コンテキスト
- A 管理 企業のインスタンスはインスタンスのある人 でに現在関連付けられている、 持続コンテキスト
- A 一戸建て 企業のインスタンスはインスタンスのある人 ることが ない(しない)の関連 と持続的な文脈.
- A 除 企業のインスタンスはインスタンスのある、 関わり、 る予定の除去から、 データベースです。
その場所には独立した主体がこのように に関連付けられていない持続的な文脈)および設定した場合 Id
dna分野 null
しなければならないこと 無根強い人ります。どの仕様に定義されてい新しい主体を問わずOpenJPAます。だからこそ私はこのことを考えるプログラムにバグOpenJPAのエラーメッセージはインコヒーレントとにかく).
他のヒント
点に注意することが "体長を追跡に関するJavaオブジェクト参照です。"
できるだけで続く同じjavaオブジェクトスーパーコンピュータを用いた再forループの場合は移りま emf = Persistence.createEntityManagerFactory("basicPU")
決のためのループを実行します。このように:
上場1:
Item item = new Item();
for (int i = 0; i < 1000; ++i) {
emf = Persistence.createEntityManagerFactory("basicPU");
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
item.setId(null);
em.persist(item);
tx.commit();
em.clear();
em.close();
}
そのためループは、
上場2:
Item item = new Item();
emf = Persistence.createEntityManagerFactory("basicPU");
for (int i = 0; i < 1000; ++i) {
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
item.setId(null);
em.persist(item);
tx.commit();
em.clear();
em.close();
}
を取得しまEntityExistException.
これは磁.createEntityManager()メソッドを返しますキャッシュされたコピーのEntityManager者は身体の安全を確保するためアイテムオブジェクトの続き前の繰り返し処理のためのループを実行します。?大きます。 ある実行が要求された以下のライン..
emf = Persistence.createEntityManagerFactory("basicPU");
for (int i = 0 ; i<10; i++){
System.out.println(emf.createEntityManager());
}
で印刷..
org.apache.openjpa.persistence.EntityManagerImpl@18105e8
org.apache.openjpa.persistence.EntityManagerImpl@9bad5a
org.apache.openjpa.persistence.EntityManagerImpl@91f005
org.apache.openjpa.persistence.EntityManagerImpl@1250ff2
org.apache.openjpa.persistence.EntityManagerImpl@3a0ab1
org.apache.openjpa.persistence.EntityManagerImpl@940f82
org.apache.openjpa.persistence.EntityManagerImpl@864e43
org.apache.openjpa.persistence.EntityManagerImpl@17c2891
org.apache.openjpa.persistence.EntityManagerImpl@4b82d2
org.apache.openjpa.persistence.EntityManagerImpl@179d854
という emf.createEntityManager()で返します新しいインスタンスのentityManager.
この上場1-上2、常に新しいEntityManagerインスタンスが上場1まで続く同じオブジェクトデータベースがリスト2を取得しまEntityExistException.どのような効果でしょうか?
と思うしている場合は新しいEntityManager両方の物件(1かつ2)まで続く同じオブジェクトデータベースでEntityManagerストッカーに関するjavaオブジェクト参照のそれぞれの繰り返してい新しいEntityManager、ほかにはないオブジェクト参照を保存/保存データベース前の繰り返しによるその他のEntityManager objectインスタンスです。
ソースコードを覗いてみたことがありますか?それはカーネルの奥深くにあります。
2563行目
OpenJPA 2.0 は、JDK 1.6 (JRE ではない) で実行するときにランタイム エンハンサーを動的にインストールできます。 ドキュメントを参照してください. 。技術的には、次を使用して Java エージェントを動的にアタッチします。 APIのアタッチ, 、必要なく -javaagent
オプション。
それで、 Item
クラスは実際に拡張されており、エンティティ マネージャーは、 null
ID とエンティティ マネージャーの終了。
エラーメッセージは、問題が何であるかがわかります。
は分離オブジェクトを永続化しようと "jee.jpa2.Item-2"
em.persistにあなたが最初のループであなたのエンティティを永続化した後、すべての後続の呼び出し(..)あなたが実際に外れエンティティ(未新しいエンティティ)に渡しています。 NULLにidフィールドを設定すると、エンティティが新しいであることを意味するものではありません。