使用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分配固定它。
但是我没有得到它,我需要修改哪些代码才能运行?
假设你有两个实体Album
和Photo
。 相册包含很多照片,所以这是一对多的关系。
相册类
@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引起的:
- 我坚持使用hibernate的实体
- 然后,我删除了一个单独的进程创build的行,没有与二级caching进行交互
- 我坚持另一个具有相同标识符的实体(我的标识符值不是自动生成的)
因此,因为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 { // ... }