我正在尝试运行这个基本的 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 分配即可修复该问题。
但是我不明白,我需要修改什么才能使代码正常工作?
假设您有两个实体
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);
这就是在持久或合并之前附加相关实体的方法。
删除
user.setId(1);
因为它是在数据库上自动生成的, 并继续执行 persist 命令。
我得到了答案,我正在使用:
em.persist(user);
我使用合并代替坚持:
em.merge(user);
但不知道,为什么坚持不起作用。 :(
如果您用于在实体中生成
id = GenerationType.AUTO
策略。
将
user.setId (1)
替换为user.setId (null)
,问题就解决了。
这里 .persist() 只会插入记录。如果我们使用 .merge() 它将检查是否存在当前 ID 的记录,如果存在,则会更新,否则会插入新记录.
我知道有点太晚了,希望每个人都能得到答案。但还需要补充一点:当设置GenerateType时,对象上的persist()预计会生成一个id。
如果用户已经为 Id 设置了一个值,hibernate 会将其视为已保存的记录,因此它会被视为已分离。
如果 id 为 null - 在这种情况下,当类型为 AUTO 或 IDENTITY 等时,会引发空指针异常,除非 id 是从表或序列等生成的。
设计:当表有一个 bean 属性作为主键时,就会发生这种情况。 仅当自动生成 id 时才必须设置GenerateType。 删除它,插入应该与用户指定的 id 一起使用。 (将属性映射到主键字段是一个糟糕的设计)
如果你在数据库中设置id为主键并且自增,那么这行代码是错误的:
user.setId(1);
试试这个:
public static void main(String[] args){
UserBean user = new UserBean();
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}
我遇到了这个问题,是二级缓存造成的:
因此,因为缓存没有失效,hibernate 假设它正在处理同一实体的分离实例。
您可以分配 ID,然后保留一个实体,例如,如果您的 ID 由用户的电子邮件表示。但是,要使其正常工作,您需要确保您的 ID 字段没有设置 @GenerateValue。
例如,如果您的实体具有电子邮件 ID 字段并设置了 @GenerateValue,则此代码将引发异常:
public class UserEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@Column(name = "email")
private String email;
...
}
并尝试保留这样的对象:
UserEntity user = new UserEntity();
user.setEmail(email);
entityManager.getTransaction().begin();
entityManager.persist(user);
entityManager.getTransaction().commit();
因此,为了使其正常工作,您需要删除@GenerateValue,但保留@ID:
public class UserEntity {
@Id
@Column(name = "email")
private String email;
...
}