我的hibernate casscade存在问题。我试图坚持一套文件。数据模型如下:
我的方案如下:
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);
所以在第一个块中我创建了一个新的TextBlock。通过级联,其余部分也应该创建。在第二个块中,我在同一文档中创建另一个文本块。在最后一个块中,我创建了另一个文本块,但使用相同的扬声器。但我不断得到以下例外:
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
在这里你可以看到我的模型类(简称):
语料库
@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;
}
文档类
@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类
@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;
}
演讲者班级
@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;
}
派对类
@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;
}
我也在使用对象/表之间的关系。尤其是小瀑布。我在stackoverflow上阅读了很多,但没有任何帮助。这是我目前的做法。当创建每个对象时,它们就像:
Speaker speaker= new Speaker("David", "Müller", pf.findById(1));
sf.createSpeaker(speaker);
speaker = sf.findSpeakerById(1);
然后将其添加到TextBlock它没有任何问题。那么有人可以帮助我吗?
问候,大卫
答案 0 :(得分:1)
您的Corpus
没有被保留。您只能级联MERGE。请参阅Document
类中的注释定义:
@ManyToOne(cascade = { CascadeType.MERGE }, fetch= FetchType.EAGER)
private Corpus corpus;
应该是:
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST }, fetch= FetchType.EAGER)
//you can simply say CascadeType.ALL if you are sure what you are doing
private Corpus corpus;
答案 1 :(得分:0)
好的,很酷,我把问题缩小到只有关系的发言人 - 党派!
我的实际新课程是: 语料库
@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 = new ArrayList<Document>();
public void addDocument(Document document) {
if (documentList != null) {
documentList.add(document);
}
}
}
文档类
@Entity
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "document_id")
private int id;
@ManyToOne
@JoinColumn(name = "corpus_id")
private Corpus corpus;
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "document")
private List<TextBlock> textBlockList = new ArrayList<TextBlock>();
public Document() {
}
public Document(Corpus corpus) {
this.corpus = corpus;
}
public void addTextBlock(TextBlock textBlock) {
if (textBlockList != null) {
textBlockList.add(textBlock);
}
}
}
TextBlock类
@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
@JoinColumn(name = "document_id")
private Document document;
@ManyToOne
private Speaker speaker;
public TextBlock() {
}
public TextBlock(Speaker speaker, String content, Document document) {
this.speaker = speaker;
this.content = content;
this.document = document;
}
}
演讲者班级
@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
private Party party;
public Speaker() {
}
public Speaker(String firstName, String lastName, Party party) {
this.firstName = firstName;
this.lastName = lastName;
this.party = party;
}
}
派对类
@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 = new ArrayList<Speaker>();
public Party() {
}
public Party(String name) {
this.name = name;
}
}
如何在扬声器和派对上设置CascadeType,当我坚持使用语料库时,扬声器和派对也会被持久化。
我的测试代码如下:
CorpusFacade cf = new CorpusFacade();
Corpus corpus = new Corpus();
Document document = new Document(corpus);
corpus.addDocument(document);
Party party = new Party("ASDF");
Speaker speaker = new Speaker("David", "Müller", party);
TextBlock textBlock1 = new TextBlock(speaker, "TB1", document);
document.addTextBlock(textBlock1);
TextBlock textBlock2 = new TextBlock(speaker, "TB1", document);
document.addTextBlock(textBlock2);
cf.createCorpus(corpus);
修改强> 对于那些在我解决问题的过程中有兴趣的人。我首先创建了一个新的演讲者和一个新派对。然后我坚持党(议长自动坚持)。之后,我将Speaker添加到TextBlock。 就这样。我无法找到语料库创建议长和派对的解决方案。 我希望它适用于某人。