Java 带有 JPA/EJB 代码的“将分离的实体传递给持久性错误”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2441598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"detached entity passed to persist error" with JPA/EJB code
提问by zengr
I am trying to run this basic JPA/EJB code:
我正在尝试运行这个基本的 JPA/EJB 代码:
public static void main(String[] args){
UserBean user = new UserBean();
user.setId(1);
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}
I get this error:
我收到此错误:
javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.JPA.Database
Any ideas?
有任何想法吗?
I search on the internet and the reason I found was:
我在互联网上搜索,我发现的原因是:
This was caused by how you created the objects, i.e. If you set the ID property explicitly. Removing ID assignment fixed it.
这是由您创建对象的方式引起的,即如果您显式设置了 ID 属性。删除 ID 分配修复了它。
But I didn't get it, what will I have to modify to get the code working?
但我没有明白,我需要修改什么才能使代码正常工作?
采纳答案by zawhtut
Let's say you have two entities Album
and Photo
. Album contains many photos, so it's a one to many relationship.
假设您有两个实体Album
和Photo
。相册包含很多照片,所以是一对多的关系。
Album class
专辑类
@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>();
}
Photo class
摄影课
@Entity
public class Photo{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer photo_id;
String photoName;
@ManyToOne(targetEntity=Album.class)
@JoinColumn(name="album_id")
Album album;
}
What you have to do before persist or merge is to set the Album reference in each photos.
在坚持或合并之前,您需要做的是在每张照片中设置相册引用。
Album myAlbum = new Album();
Photo photo1 = new Photo();
Photo photo2 = new Photo();
photo1.setAlbum(myAlbum);
photo2.setAlbum(myAlbum);
That is how to attach the related entity before you persist or merge.
这就是在持久化或合并之前附加相关实体的方法。
回答by zengr
I got the answer, I was using:
我得到了答案,我正在使用:
em.persist(user);
I used merge in place of persist:
我用合并代替坚持:
em.merge(user);
But no idea, why persist didn't work. :(
但不知道,为什么坚持不起作用。:(
回答by Tomislav Nakic-Alfirevic
The error occurs because the object's ID is set. Hibernate distinguishes between transient and detached objects and persist
works only with transient objects. If persist
concludes the object is detached (which it will because the ID is set), it will return the "detached object passed to persist" error. You can find more details hereand here.
发生错误是因为设置了对象的 ID。Hibernate 区分瞬态对象和分离对象,并且persist
仅适用于瞬态对象。如果persist
得出结论该对象已分离(因为设置了 ID),它将返回“已分离对象传递给持久化”错误。您可以在此处和此处找到更多详细信息。
However, this only applies ifyou have specified the primary key to be auto-generated: if the field is configured to always be set manually, then your code works.
然而,这仅适用于如果您指定的主键是自动生成的:如果该字段设置为始终手动设置,那么你的代码的作品。
回答by hertzsprung
I had this problem and it was caused by the second level cache:
我有这个问题,它是由二级缓存引起的:
- I persisted an entity using hibernate
- Then I deleted the row created from a separate process that didn't interact with the second level cache
- I persisted another entity with the same identifier (my identifier values are not auto-generated)
- 我使用 hibernate 持久化了一个实体
- 然后我删除了从不与二级缓存交互的单独进程创建的行
- 我保留了另一个具有相同标识符的实体(我的标识符值不是自动生成的)
Hence, because the cache wasn't invalidated, hibernate assumed that it was dealing with a detached instance of the same entity.
因此,因为缓存没有失效,hibernate 假定它正在处理同一实体的分离实例。
回答by Ammar Bozorgvar
remove
消除
user.setId(1);
because it is auto generate on the DB, and continue with persist command.
因为它是在数据库上自动生成的,并继续执行持久命令。
回答by haripriya
I know its kind of too late and proly every one got the answer. But little bit more to add to this: when GenerateType is set, persist() on an object is expected to get an id generated.
我知道为时已晚,每个人都得到了答案。但是要添加一点:当设置 GenerateType 时,对象上的 persist() 预计会生成一个 id。
If there is a value set to the Id by user already, hibernate treats it as saved record and so it is treated as detached.
如果用户已经为 Id 设置了一个值,hibernate 会将其视为已保存的记录,因此将其视为已分离。
if the id is null - in this situation a null pointer exception is raised when the type is AUTO or IDENTITY etc unless the id is generated from a table or a sequece etc.
如果 id 为空 - 在这种情况下,当类型为 AUTO 或 IDENTITY 等时,会引发空指针异常,除非该 id 是从表或序列等生成的。
design: this happens when the table has a bean property as primary key. GenerateType must be set only when an id is autogenerated. remove this and the insert should work with the user specified id. (it is a bad design to have a property mapped to primary key field)
设计:当表有一个 bean 属性作为主键时会发生这种情况。仅当自动生成 id 时才必须设置 GenerateType。删除它,插入应该与用户指定的 id 一起使用。(将属性映射到主键字段是一种糟糕的设计)
回答by PSR
Here .persist()only will insert the record.If we use .merge()it will check is there any record exist with the current ID, If it exists, it will update otherwise it will insert a new record.
这里.persist()只会插入记录。如果我们使用.merge()它将检查是否存在任何具有当前 ID 的记录,如果存在,它将更新,否则将插入新记录。
回答by Sergio Ordó?ez
if you use to generate the id = GenerationType.AUTO
strategy in your entity.
如果您用于id = GenerationType.AUTO
在实体中生成策略。
Replaces user.setId (1)
by user.setId (null)
, and the problem is solved.
替换user.setId (1)
为user.setId (null)
,问题解决。
回答by Nemus
If you set id in your database to be primary key and autoincrement, then this line of code is wrong:
如果你在你的数据库中将id设置为主键和自增,那么这行代码是错误的:
user.setId(1);
Try with this:
试试这个:
public static void main(String[] args){
UserBean user = new UserBean();
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}