1

私は、EclipseLink と Hibernate プロバイダーの両方に対してテストする、非常に単純なコンソール ベースの (アプリケーション サーバーにデプロイされたものではない) JPA プログラムを持っています。すべてのコードは JPA であるため、プロバイダーを問題なく切り替えることができると考えました。ただし、Hibernate をプロバイダーとして使用するとプログラムは成功しますが、EclipseLink では失敗します。

重要な部分は次のとおりです (私はファイアウォールの背後にいるため、「別のドメインからの JavaScript が必要です...」が原因で書式設定が表示されないため、適切に書式設定されていない場合は申し訳ありません - 自宅から書式設定を行います):

em.getTransaction().begin();
Employee emp = service.createEmployee(id, "John Doe", 45000,1);
em.getTransaction().commit();                                        
System.out.println("Persisted "+emp);
em.getTransaction().begin();
em.getTransaction().commit();

以前は 2 番目の空のトランザクション内でいくつかのことを行っていましたが、問題を絞り込むと、何もせずに begin() と commit() をすぐに実行しても失敗することに気付きました。興味深い部分は、EclipseLink (投稿の下部にあるスタック トレースを参照) が、更新されているエンティティ Specialty の id 属性について不平を言っているように見えることです。

Employee エンティティには、Specialty エンティティへの外部キーがあります (各 Employee には Specialty があります)。つまり、Employee からの多対 1 の関係です。

 @Entity
 public class Employee {
 @Id                                                            
 @Basic(optional = false)                                       
 @NotNull                                                       
 private int id;                                                
 private String name;                                           
 private long salary;                                           
 @JoinColumn(name = "spc_id", referencedColumnName = "id")      
 @ManyToOne(optional = false)                                   
 private Specialty spcId;
 ...}

Specialty クラスは次のように定義されます。

@Entity                                                  
public class Specialty {                                 
@Id                                                  
@Basic(optional = false)                             
@NotNull                                             
private int id;
... }

Hibernate を JPA プロバイダーとして使用すると、コードはスムーズに実行されます。EclipseLink を使用すると、この投稿の下部にあるスタック トレースで失敗します。

更新: さらに実験を行ったところ、次のコードが両方のプロバイダーで機能することがわかりました。

em.getTransaction().begin();                                      
Employee emp = service.createEmployee(id, "John Doe", 45000, 1);  
em.getTransaction().commit();                                     
System.out.println("Persisted " + emp);                           
EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();                                     
em2.getTransaction().commit();                                    
em2.close();          

同じエンティティマネージャオブジェクトでトランザクションを begin() / commit() しようとすると EclipseLink が失敗する理由 (em - 投稿の冒頭のコードを参照)、さらにそのような不可解なメッセージで失敗する理由 (苦情クラス Specialty の主キーが更新されることについて)。

スタックトレース:

[java] [EL Info]: 2012-07-12 11:21:09.453--ServerSession(23846608)--EclipseLink, version: Eclipse Persistence Services - 2.4.0.v20120608-r11652
 [java] [EL Info]: connection: 2012-07-12 11:21:09.59--ServerSession(23846608)--file:/home/mperdikeas/playground/jpa/01-employee-job/prj/use/build/employeetest.jar_EmployeeService login successful
 [java] Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
 [java] Exception Description: The attribute [id] of class [mp.Specialty] is mapped to a primary key column in the database. Updates are not allowed.
 [java]     at org.eclipse.persistence.internal.Persisted mp.Employee@ea70f2
 [java] [EL Warning]: 2012-07-12 11:21:09.735--UnitOfWork(32118258)--Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
 [java] Exception Description: The attribute [id] of class [mp.Specialty] is mapped to a primary key column in the database. Updates are not allowed.
 [java] [EL Info]: connection: 2012-07-12 11:21:09.738--ServerSession(23846608)--file:/home/mperdikeas/playground/jpa/01-employee-job/prj/use/buildjpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
 [java]     at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
 [java]     at mp.EmployeeTest.main(EmployeeTest.java:29)
 [java] Caused by: Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
 [java] Exception Description: The attribute [id] of class [mp.Specialty] is mapped to a primary key column in the database. Updates are not allowed.
 [java]     at org.eclipse.persistence.exceptions.ValidationException.primaryKeyUpdateDisallowed(ValidationException.java:2458)
 [java]     at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.writeFromObjectIntoRowWithChangeRecord(AbstractDirectMapping.java:1214)
 [java]     at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildRowForUpdateWithChangeSet(ObjectBuilder.java:1378)
 [java]     at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:1003)
 [java]     at org.eclipse.persistence.queries.UpdateObjectQuery.executeCommitWithChangeSet(UpdateObjectQuery.java:84)
 [java]     at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:286)
 [java]     at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
 [java]     at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852)
 [java]     at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:751)
 [java]     at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
 [java]     at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2875)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1535)
 [java]     at org.eclipse.persistence.internal.sessions.CommitManager.commitChangedObjectsForClassWithChangeSet(CommitManager.java:265)
 [java]     at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:128)
 [java]     at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3914)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1419)
 [java]     at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:634)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1509)
 [java]     at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:266)
 [java]     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1147)
 [java]     at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
 [java]     ... 2 more
 [java] /employeetest.jar_EmployeeService logout successful
4

3 に答える 3

2

EclipseLink では PK を更新できません (この PK に FK がない場合、一部の DBMS ではこれが許可されます)。

2 つの回避策があります。

  1. 古いレコードを削除してから、新しいレコードを挿入してみてください。
  2. ビジネス PK の代わりにサロゲート PK を使用します (ビジネス PK フィールドに一意の制約を追加することもできます)。この場合、ダミーのサロゲート キーは変更されません。両方のキーの比較を次に示します。
于 2013-07-21T13:54:56.920 に答える
0

http://blogs.nologin.es/rickyepoderi/index.php?/archives/95-Weaving-Problem-in-EclipseLink.html<property name="eclipselink.weaving.internal" value="false"/>に従って試してください。

于 2015-08-17T17:32:04.037 に答える