I use annotations with hibernate-3.1 rc3. I have discover, that using CascadeType.ALL is not equivalent to {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH}.
Here are my entity classes Report and Auftritt with Many-To-One relation:
Code:
package ftek.model;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity(access = AccessType.FIELD)
@Table(schema = "report_apps", name = "REPORTS")
public class Report extends ftek.shared.HibernatePersistent<Long> {
@Id
@Column(name = "REP_ID")
private Long id;
// @ManyToOne(cascade = {CascadeType.ALL}, fetch=FetchType.EAGER)
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH}, fetch=FetchType.EAGER)
@JoinColumn(name="REP_AFT_ID", nullable = false, updatable = true)
private Auftritt auftritt;
@Column(name = "BEZEICHNUNG")
private java.lang.String bezeichnung;
public Report() {
super();
}
public Report(java.lang.Long id) {
super(id);
}
public Auftritt getAuftritt() {
return this.auftritt;
}
public void setAuftritt(Auftritt auftritt) {
this.auftritt = auftritt;
}
public java.lang.String getBezeichnung() {
return this.bezeichnung;
}
public void setBezeichnung(java.lang.String bezeichnung) {
this.bezeichnung = bezeichnung;
}
public Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
}
Code:
package ftek.model;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratorType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity(access = AccessType.FIELD)
@SequenceGenerator(name = "SEQ_AFT", sequenceName = "FLEXUP.flx_user_sec")
@Table(schema = "report_apps", name = "AUFTRITTE_BASE")
public class Auftritt extends ftek.shared.HibernatePersistent<Long> {
@Id(generate = GeneratorType.SEQUENCE, generator = "SEQ_AFT")
@Column(name = "AFT_ID")
private Long id;
@Column(name = "AUFTRITT")
private java.lang.String text;
@OneToMany(cascade = { CascadeType.PERSIST }, mappedBy = "auftritt")
protected Set<Report> reports = new HashSet<Report>();
@Column(name = "AFT_SPB_ID")
private Long spbId = new Long(1);
public Auftritt() {
super();
}
public Auftritt(java.lang.Long id) {
super();
this.setId(id);
}
public java.lang.String getText() {
return this.text;
}
public void setText(java.lang.String text) {
this.text = text;
}
public Set<Report> getReports() {
return reports;
}
public void setReports(Set<Report> reports) {
this.reports = reports;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
And my code, that uses these classes:
Code:
Auftritt aft = new Auftritt();
aft.setText("test");
Report report = new Report(-1L);
report.setBezeichnung("test");
report.setAuftritt(aft);
aft.getReports().add(report);
report.persist();
I expect, that aft will be persisted using cascading, when I persist report. It works fine, if
@ManyToOne(cascade = {CascadeType.ALL})
syntax is used, and fails in case of
@ManyToOne(cascade = {CascadeType.PERSIST})
with following exception:
Quote:
Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value: ftek.model.Report.auftritt
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:265)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:167)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:114)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:98)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:501)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:491)
at ftek.shared.HibernatePersistent.persist(HibernatePersistent.java:48)
at ftek.TestMain.main(TestMain.java:24)
I also have tried to use full list of possible values of CascadeType
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH} )
with same result.
Looks like a bug?