簡體   English   中英

在OneToMany中使用Hibernate持久化對象

[英]Persist Object with Hibernate in OneToMany

我的休眠級聯有問題。 我正在嘗試保留一組文檔。 數據模型如下:

  • 語料庫1 --- n文檔1 --- n TextBlock n --- 1演講者n- 1派對

我的情況如下:

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,它可以正常工作。 那有人可以幫我嗎?

大衛問候

您的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;

好的,很酷,我將問題縮小到關系的議長方。

我實際的新課程是: 語料庫課程

@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。 就這樣。 我找不到一個解決方案,即語料庫也創建了演講者和聚會。 我希望它對某人有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM