[英]Persist Object with Hibernate in OneToMany
I have a problem with my hibernate casscade. 我的休眠级联有问题。 I'm trying to persist a set of document.
我正在尝试保留一组文档。 The data model is the following:
数据模型如下:
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. 因此,在第一步中,我创建了一个新的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 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;
}
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.
我在stackoverflow上读了很多书,但没有任何帮助。 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. 然后将其添加到TextBlock,它可以正常工作。 So can somebody help me?
那有人可以帮我吗?
Greeting, David 大卫问候
Your Corpus
does not get persisted. 您的
Corpus
不会持续存在。 You cascade only MERGE. 您只能级联MERGE。 See the annotation definition in your
Document
class: 请参阅
Document
类中的注释定义:
@ManyToOne(cascade = { CascadeType.MERGE }, fetch= FetchType.EAGER)
private Corpus corpus;
should be: 应该:
@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;
Ok, cool I narrowed the problem to only the Speaker-Party-Side of the Relations! 好的,很酷,我将问题缩小到关系的议长方。
My actual new classes are: 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 = new ArrayList<Document>();
public void addDocument(Document document) {
if (documentList != null) {
documentList.add(document);
}
}
}
Document Class 文件类别
@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 Class 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;
}
}
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
private Party party;
public Speaker() {
}
public Speaker(String firstName, String lastName, Party party) {
this.firstName = firstName;
this.lastName = lastName;
this.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 = new ArrayList<Speaker>();
public Party() {
}
public Party(String name) {
this.name = name;
}
}
How do I set the CascadeType on Speaker and Party that when I persist a Corpus the Speaker and the Party is persited too. 我如何在“演讲者和聚会”上设置CascadeType,当我保留语料库时,“演讲者和聚会”也保持不变。
My test code is the following: 我的测试代码如下:
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);
Edit For those who are interessted in my solution of the problem. 编辑对于那些对我的问题感兴趣的人。 I create first a new Speaker and a new Party.
我首先创建一个新的演讲者和一个新的聚会。 Then I persist the Party (the Speaker persists automatically).
然后我坚持党(议长自动坚持)。 After that I add the Speaker to the TextBlock.
之后,我将Speaker添加到TextBlock。 Thats all.
就这样。 I couldn't find asolution where the corpus creates the Speaker and Party too.
我找不到一个解决方案,即语料库也创建了演讲者和聚会。 I hope it works for someone.
我希望它对某人有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.