我需要坚持一个具有分离关系的新实体,但是,在坚持(...)的那一刻,我得到一个例外:
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: model.Subject
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1153)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678)
at Application.method3(Application.java:90)
at Application.main(Application.java:41)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: model.Subject
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.tuple.entity.AbstractEntityTuplizer$IncrediblySillyJpaMapsIdMappedIdentifierValueMarshaller.getIdentifier(AbstractEntityTuplizer.java:375)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:223)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:3850)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:3558)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:531)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:102)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672)
... 2 more
实体: 受试者
@Entity
@Table(name = "TAsignaturas", uniqueConstraints = { @UniqueConstraint(columnNames = {
"nombre", "curso" }) })
public class Subject implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "seq")
@SequenceGenerator(name = "seq", sequenceName = "ASIGNATURAS_SEQUENCE", allocationSize = 1, initialValue = 1)
private Long id;
private String nombre, curso;
private int creditos;
// @Transient
@OneToMany(mappedBy = "subject")
private Set<Matricula> matriculas;
public Subject() {
matriculas = new HashSet<Matricula>();
}
public Subject(String nombre, String curso, int creditos) {
this.setNombre(nombre);
this.setCurso(curso);
this.setCreditos(creditos);
this.matriculas = new HashSet<Matricula>();
}
public Matricula addMatricula(Matricula m) {
m.setSubject(this);
this.matriculas.add(m);
return m;
}
public void removeMatricula(Matricula m) {
this.matriculas.remove(m);
}
[...]
}
Alumno
@Entity
public class Alumno implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private static final long serialVersionUID = 1L;
@OneToMany(mappedBy = "alumno")
private Set<Matricula> matriculadas;
public Alumno() {
super();
this.matriculadas = new HashSet<Matricula>();
}
public Matricula addMatricula(Matricula m) {
m.setAlumno(this);
this.matriculadas.add(m);
return m;
}
public void removeMatricula(Matricula m) {
this.matriculadas.remove(m);
}
[...]
}
Matricula
@IdClass(MatriculaKey.class)
@Entity
public class Matricula implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@ManyToOne
private Alumno alumno;
@Id
@ManyToOne
private Subject subject;
public Matricula() {
super();
}
public Matricula(Alumno a, Subject s) {
super();
this.alumno = a;
this.subject = s;
this.alumno.addMatricula(this);
this.subject.addMatricula(this);
}
public void addAlumno(Alumno a) {
a.getMatriculadas().add(this);
this.alumno = a;
}
public void removeAlumno(Alumno a) {
a.getMatriculadas().remove(this);
this.setAlumno(null);
}
public void addSubject(Subject s) {
s._getMatriculas().add(this);
this.subject = s;
}
public void removeSubject(Subject s) {
s._getMatriculas().remove(this);
this.setSubject(null);
}
[...]
}
启动例外的主要代码:
public class Application {
Subject sub;
public static void main(String[] args) {
Application a = new Application();
// method2
EntityManager em = Jpa.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
a.method2();
tx.commit();
if (em.isOpen())
em.close();
// method3
em = Jpa.createEntityManager();
tx = em.getTransaction();
tx.begin();
a.method2();
tx.commit();
if (em.isOpen())
em.close();
}
//It´s necessary execute this method before to method3, in two different transactions, non in one transaction
private void method2() {
this.sub = Jpa.getManager().find(Subject.class, 2L);
}
private void method3() {
Alumno al = new Alumno();
Matricula m = new Matricula(al, this.sub);
Jpa.getManager().persist(m); //error. merge doesn´t work nor
}
}
我糟糕的解决方案的主要代码:
public class Application {
Subject sub;
public static void main(String[] args) {
Application a = new Application();
// method2
EntityManager em = Jpa.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
a.method2();
tx.commit();
if (em.isOpen())
em.close();
// method3
em = Jpa.createEntityManager();
tx = em.getTransaction();
tx.begin();
a.method2();
tx.commit();
if (em.isOpen())
em.close();
}
private void method2() {
this.sub = Jpa.getManager().find(Subject.class, 2L);
}
private void method3() {
Alumno al = new Alumno();
//aux transient subject
Subject s=new Subject();
Matricula m = new Matricula(al, s);
//now, I can persist correctly
Jpa.getManager().persist(m);
//replace the aux subject...
m.removeSubject(s);
m.addSubject(sub);
//and update
Jpa.getManager().merge(m);
}
}
是否存在针对此问题的更简单的解决方案?
米格尔