使用JPA / EJB代码“分离的实体传递给持久性错误”

我试图运行这个基本的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 

有任何想法吗?

我在互联网上search,我发现的原因是:

这是由你如何创build的对象,即如果你明确设置ID属性。 删除ID分配固定它。

但是我没有得到它,我需要修改哪些代码才能运行?

ERD

假设你有两个实体AlbumPhoto 。 相册包含很多照片,所以这是一对多的关系。

相册类

 @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); 

这是如何附加相关的实体,然后再坚持或合并。

发生该错误是因为对象的ID已设置。 Hibernate区分临时对象和分离对象,并且只对瞬态对象persist工作。 如果persist结束对象被分离(这将因为ID被设置),它将返回“分离的对象传递给持久”错误。 你可以在这里和这里find更多的细节。

但是,只有您指定主键为自动生成的情况下才适用:如果将字段configuration为始终手动设置,那么您的代码将起作用。

去掉

 user.setId(1); 

因为它是在数据库上自动生成的,并继续执行持久命令。

我得到了答案,我正在使用:

 em.persist(user); 

我用合并代替坚持:

 em.merge(user); 

但不知道,为什么坚持不工作。 🙁

如果您使用在您的实体中生成id = GenerationType.AUTO策略。

user.setId (null)replaceuser.setId (1) ,问题就解决了。

我知道这种太晚和pr every,每个人都有答案。 但是增加一点点:在设置GenerateType时,对象上的persist()需要生成一个id。

如果用户已经有了一个设置为Id的值,hibernate会将其视为保存的logging,因此将其视为已分离。

如果id为空 – 在这种情况下,当types为AUTO或IDENTITY等时,会引发空指针exception,除非该id是从表或后缀等中生成的。

devise:当表具有一个bean属性作为主键时会发生这种情况。 GenerateType只有在自动生成id时才能设置。 删除这个插入应该与用户指定的ID一起工作。 (将属性映射到主键字段是一个糟糕的devise)

这里.persist()只会插入logging。如果我们使用.merge(),它会检查当前ID是否存在任何logging,如果存在则更新,否则会插入新logging。

我有这个问题,这是由二级caching引起的:

  1. 我坚持使用hibernate的实体
  2. 然后,我删除了一个单独的进程创build的行,没有与二级caching进行交互
  3. 我坚持另一个具有相同标识符的实体(我的标识符值不是自动生成的)

因此,因为caching没有失效,所以hibernate假定它正在处理同一实体的分离实例。

如果你在你的数据库中设置id是主键和自动增量,那么这行代码是错误的:

 user.setId(1); 

试试这个:

 public static void main(String[] args){ UserBean user = new UserBean(); user.setUserName("name1"); user.setPassword("passwd1"); em.persist(user); } 

错误的另一个原因是你的实体对象没有实现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 { // ... }