Java &引用;已分离实体传递到持久化错误“;使用JPA/EJB代码
我正在尝试运行以下基本JPA/EJB代码:Java &引用;已分离实体传递到持久化错误“;使用JPA/EJB代码,java,jpa,ejb-3.0,Java,Jpa,Ejb 3.0,我正在尝试运行以下基本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.ej
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分配修复了它
但是我没有得到它,我需要修改什么才能让代码正常工作?我得到了答案,我使用了:
em.persist(user);
我使用“合并”代替“持久化”:
em.merge(user);
但不知道,为什么坚持不起作用(发生错误是因为设置了对象的ID。Hibernate区分暂时对象和分离对象,并且
persist
仅适用于暂时对象。如果persist
得出对象已分离的结论(由于ID已设置),它将返回“传递给persist的分离对象”错误。您可以找到更多详细信息和
但是,这仅适用于指定要自动生成的主键的情况:如果将字段配置为始终手动设置,则代码有效。
假设您有两个实体相册
和照片
。相册包含许多照片,因此是一对多关系
专辑类
@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);
因为它是在数据库上自动生成的,
然后继续使用persist命令。我知道这有点太晚了,而且每个人都得到了答案。但还有一点需要补充:当设置GenerateType时,对象上的persist()需要生成一个id 如果用户已经为Id设置了一个值,hibernate将其视为已保存的记录,因此将其视为已分离 如果id为null-在这种情况下,当类型为AUTO或IDENTITY等时会引发null指针异常,除非id是从表或序列等生成的 设计:当表有一个bean属性作为主键时,就会发生这种情况。 仅当自动生成id时,才能设置GenerateType。 删除此项,插入项应使用用户指定的id。
(将属性映射到主键字段是一种糟糕的设计)此处.persist()只会插入记录。如果使用.merge()它将检查是否存在具有当前ID的记录,如果存在,它将更新,否则它将插入新记录。如果您在实体中使用生成
ID=GenerationType.AUTO
策略
将
user.setId(1)
替换为user.setId(null)
,问题就解决了。如果将数据库中的id设置为主键并自动递增,则此行代码错误:
user.setId(1);
试试这个:
public static void main(String[] args){
UserBean user = new UserBean();
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}
当我说,我使用的是JPA而不是Hibernate时,我在技术上是正确的吗?所以,上面的陈述不应该适用于正确的吗?我是JPA的新手(准确地说是3天:P)Sun的JPA Javadoc()和Toplink的JPA Javadoc()完全相同,表明你在技术上是正确的。然而,它实际上归结为规范所说的persist()很遗憾,我不知道这是什么。这个解决方案对我有效。我一直在保存一个对象,将ID存储在某个地方。然后我想用一个新值覆盖现有的对象,所以我创建了该对象,将ID复制回来,当我试图保存时,它爆炸了。最后,我不得不重新查询数据库(findById),进行更改,然后保留该对象。这不是解决方案!我知道,但这对我有效。这里还有其他对您有效的答案吗?如果是,我将非常乐意选择它。它有效是因为您的对象已从hibernate会话中分离,或者对象是暂时的,但hibernate认为它已分离,因为您声明的主键,使用merge将对象再次附加到会话,这使您能够更新数据库中的对象;请参阅:如果使用泛型,则无需使用“targetEntity=Photo.class”您好,在将相册对象设置为photo1和photo2之后…我们必须保存照片或相册列表的对象是什么?我尝试了,我知道出现了此错误:
分离实体传递到persist
在得到您的答案之前,我花费了大量时间。非常感谢!