2

WebSphere7でJPAとEJBを使用しています。

私は次のクラスを持っています:

@Entity
@Table(name="WIDGET")
public class Widget implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  private String name;
  private String details;
/* getters and setters */
}

私はそのようなDAOを持っています:

@Stateless
public class WidgetDAO implements WidgetDAOLocal {
  @PersistenceUnit
  private EntityManagerFactory emf;
  private EntityManager em;

  public EntityManager getEntityManager() {
    if (emf == null) {
      throw new Exception();
    }
    return emf.createEntityManager;
  }

  public Widget getWidget(Long id) {
    Widget widget = null;
    EntityManager em = getEntityManager();
    try {
      widget = (Widget)em.find(Widget.class, widgetId);
    } finally {
      em.close();
    }
    return widget;
  }

  public Widget createWidget(Widget widget) {
    EntityManager em = getEntityManager();
    try {
      em.persist(widget);
      em.flush();
    } finally {
      em.close();
    }
    return widget;
  }

  public Widget updateWidget(Widget widget) {
    EntityManager em = getEntityManager();
    try {
      widget = getEntityManager().merge(widget);
      em.flush();
    } finally {
      em.close();
    }
    return widget;
  }

}

作成は正常に機能し、ウィジェットがデータベースに表示されます。

しかし、マージを実行しようとすると、エラーが発生します。マージを行うためのコードと私が得るエラーは次のとおりです。

public WidgetService {

  @EJB
  private WidgetDAO widgetDAO;

  public WidgetDAO getWidgetDAO() {
    return this.widgetDAO;
  }

  public Widget getWidget(Long id) {
     return this.getWidgetDAO().getWidget(id);
  }

  public void updateDetails(Long widgetId, String details) {
    Widget w = this.getWidget(widgetId);
    w.setDetails(details);
    this.widgetDAO.updateWidget(w);
  }

}

エラーは次のとおりです。

Exception caught from before_completion synchronization operation: 
<openjpa-1.2.1-SNAPSHOT-r422266:686069 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException:
The generated value processing detected an existing value assigned to this field: com.mydomain.domain.Widget.id.  
This existing value was either provided via an initializer or by calling the setter method.  
You either need to remove the @GeneratedValue annotation or modify the code to the initializer processing.

これに関するどんな助けも大歓迎です!

4

2 に答える 2

0

Mergeはエンティティのコピーを取得し、それをデタッチして新しいエンティティを保持します。これにより、古いIDからIDを設定しようとし、生成された値で競合が発生すると推測されます。オブジェクトを更新したいだけの場合は、トランザクション内で更新してコミットする必要があります。

于 2012-05-25T23:45:38.350 に答える
0

皆さんの助けに感謝します、私はそれを理解しました、これが問題の原因と私のために働いた解決策です。

私のDAOではこれを行っていました:

@Stateless 
public class WidgetDAO implements WidgetDAOLocal {
   @PersistenceUnit
   private EntityManagerFactory emf;
   private EntityManager em;

  public EntityManager getEntityManager() {
     if (emf == null) {
       throw new Exception();
     }
     return emf.createEntityManager;
   } 

EntityManagerFactoryは@PersistenceUnitアノテーションを介して注入されていたため、エンティティーは「アプリケーション管理」であり、WebSphereとのある種の競合を引き起こしていました。

コードを次のように変更しました。

@Stateless 
public class WidgetDAO implements WidgetDAOLocal {
  @PersistenceContext 
  private EntityManager em;

  public EntityManager getEntityManager() {
    return em;
  } 

  public Widget updateWidget(Widget widget) throws Exception {
    return getEntityManager().merge(widget);
  }

@PersistenceContextアノテーションにより、エンティティは「コンテナ管理」になり、すべてが機能するようになります。

ここにすべての助けと提案をありがとう。一日の終わりに、私はここのドキュメントの「エンティティの管理」セクションに再び焦点を合わせた後、解決策を考え出しました。

http://docs.oracle.com/javaee/5/tutorial/doc/

于 2012-05-28T15:10:30.423 に答える