この基本的なJPA/EJBコードを実行しようとしています:
public static void main(String[] args){
UserBean user = new UserBean();
user.setId(1);
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}
私はこのエラーを受け取ります:
javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.JPA.Database
何か案は?
インターネットで検索しましたが、見つけた理由は次のとおりです。
これは、オブジェクトの作成方法、つまりIDプロパティを明示的に設定した場合に発生しました。 ID割り当てを削除すると修正されました。
しかし、私はそれを手に入れませんでした。コードを機能させるために何を修正する必要がありますか?
2つのエンティティAlbum
とPhoto
があるとします。アルバムには多くの写真が含まれているため、1対多の関係です。
アルバムクラス
@Entity
public class Album {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer albumId;
String albumName;
@OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true)
Set<Photo> photos = new HashSet<Photo>();
}
写真のクラス
@Entity
public class Photo{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer photo_id;
String photoName;
@ManyToOne(targetEntity=Album.class)
@JoinColumn(name="album_id")
Album album;
}
永続化またはマージする前に行う必要があるのは、各写真にアルバム参照を設定することです。
Album myAlbum = new Album();
Photo photo1 = new Photo();
Photo photo2 = new Photo();
photo1.setAlbum(myAlbum);
photo2.setAlbum(myAlbum);
これは、永続化またはマージする前に関連エンティティをアタッチする方法です。
削除する
user.setId(1);
これはDB上で自動生成され、persistコマンドを続行するためです。
私は答えを得ました、私は使っていました:
em.persist(user);
Persistの代わりにmergeを使用しました。
em.merge(user);
しかし、どうして永続化が機能しなかったのかわかりません。 :(
エンティティでid = GenerationType.AUTO
戦略の生成に使用する場合。
user.setId (1)
をuser.setId (null)
に置き換え、問題が解決しました。
私はその種類が遅すぎることを知っており、すべての人が答えを得ました。ただし、これに追加することはもう少しあります。GenerateTypeが設定されている場合、オブジェクトのpersist()はIDを生成することが期待されます。
ユーザーによってIdに既に設定されている値がある場合、hibernateはその値を保存済みレコードとして扱うため、デタッチされたものとして扱われます。
idがnullの場合-この状況では、idがテーブルまたはシーケンスなどから生成されない限り、タイプがAUTOまたはIDENTITYなどの場合、nullポインタ例外が発生します。
設計:これは、テーブルに主キーとしてBeanプロパティがある場合に発生します。 GenerateTypeは、IDが自動生成される場合にのみ設定する必要があります。これを削除すると、ユーザーが指定したIDで挿入が機能するはずです。 (プロパティを主キーフィールドにマップするのは悪い設計です)
ここで。persist()はレコードを挿入するだけです。。merge()を使用すると、現在のIDを持つレコードが存在するかどうかがチェックされます。それ以外の場合は更新され、新しいレコードが挿入されます。
データベースでidを主キーおよび自動インクリメントに設定した場合、次のコード行は間違っています。
user.setId(1);
これで試してください:
public static void main(String[] args){
UserBean user = new UserBean();
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}
この問題が発生したのは、2次キャッシュが原因でした。
したがって、キャッシュは無効化されていないため、休止状態は同じエンティティの切り離されたインスタンスを処理していると想定していました。
エンティティオブジェクトがSerializable
インターフェイスを実装していないというエラーの別の理由
@Entity
@Table(name = OddInstance.objectName, uniqueConstraints = @UniqueConstraint(columnNames = {"alias"}))
@NamedQueries({
@NamedQuery(name=OddInstance.findByAlias,
query="from OddInstance where alias = :alias"),
@NamedQuery(name=OddInstance.findAll,
query="from OddInstance")
})
public class OddInstance implements Serializable {
// ...
}