I have a problem with my hibernate casscade. I'm trying to persist a set of document. The data model is the following:
- Corpus 1 --- n Document 1 --- n TextBlock n --- 1 Speaker n --- 1 Party
My scenario is the following:
SpeakerFacade sf = new SpeakerFacade();
TextBlockFacade tf = new TextBlockFacade();
Corpus corpus = new Corpus();
Document doc1 = new Document(corpus);
TextBlock tb1 = new TextBlock(new Speaker("David", "Müller", new Party("ASDF")), "TB1", doc1);
tf.createTextBlock(tb1);
TextBlock tb2 = new TextBlock(new Speaker("Benedikt", "Müller", new Party("JKLÖ")), "TB2", doc1);
tf.createTextBlock(tb2);
TextBlock tb3 = new TextBlock(sf.findPersonById(1), "TB3", doc1);
tf.createTextBlock(tb3);
So in the first block I create a new TextBlock. With the cascade the rest should be created too. In the second block I create another textblock within the same document. In the last block I create also antoher textblock but with the same speaker. But I constantly getting the following exception:
Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : de.uniba.speechanalyser.persist.model.Document.corpus -> de.uniba.speechanalyser.persist.model.Corpus
Here you can see my model classes (in short form):
Corpus Class
@Entity
public class Corpus implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "corpus_id")
private int id;
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "corpus")
private List<Document> documentList;
}
Document Class
@Entity
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "document_id")
private int id;
@ManyToOne(cascade = { CascadeType.MERGE },fetch= FetchType.EAGER)
private Corpus corpus;
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "document")
private List<TextBlock> textBlockList;
}
TextBlock Class
@Entity
public class TextBlock implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "textblock_id")
private int id;
@Lob
String content;
@ManyToOne(cascade = { CascadeType.MERGE },fetch= FetchType.EAGER)
private Document document;
@ManyToOne(cascade = { CascadeType.MERGE },fetch= FetchType.EAGER)
private Speaker speaker;
}
Speaker Class
@Entity
@NamedQueries({
@NamedQuery(name = "Speaker.findSpeakerByName", query = "select s from Speaker s where s.firstName = :firstName and s.lastName = :lastName") })
public class Speaker implements Serializable {
private static final long serialVersionUID = 1L;
public static final String FIND_BY_NAME = "Speaker.findSpeakerByName";
@Id
@GeneratedValue
@Column(name = "speaker_id")
private int id;
private String firstName;
private String lastName;
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "speaker")
private List<TextBlock> textBlock;
@ManyToOne(cascade = { CascadeType.MERGE },fetch= FetchType.EAGER)
private Party party;
}
Party Class
@Entity
@NamedQueries({
@NamedQuery(name = "Party.findPartyByName", query = "select p from Party p where p.name = :name")
})
public class Party implements Serializable {
private static final long serialVersionUID = 1L;
public static final String FIND_BY_NAME = "Party.findPartyByName";
@Id
@GeneratedValue
@Column(name = "party_id")
private int id;
private String name;
@OneToMany(cascade = { CascadeType.ALL}, mappedBy = "party")
private List<Speaker> speakerList;
}
I'm also strugeling with the relations between the object/tables. Especially with the cascades. I read a lot on stackoverflow but nothing helped really. This is my current approach. When a create each object on it's own like:
Speaker speaker= new Speaker("David", "Müller", pf.findById(1));
sf.createSpeaker(speaker);
speaker = sf.findSpeakerById(1);
And then add it to the TextBlock it works without any problem. So can somebody help me?
Greeting, David