的名單上有在Java中2 POJO類:短語和標籤,在許多一對多的關係:JPA許多一對多的關係,保持IDS
Phrase.java
@Entity @EntityListeners(value={PhraseListener.class}) public class Phrase { @Id @GeneratedValue @Column(name="id") private Long phraseId; @Column(nullable=false) private String text; @ManyToMany(cascade=CascadeType.ALL) @JoinTable(name="phrase_has_tag", joinColumns={@JoinColumn(name="phrase_id",referencedColumnName="id")}, inverseJoinColumns={@JoinColumn(name="tag_uname",referencedColumnName="uname")}) private Collection<Tag> tagObjects; @Transient private Set<String> tags; public Phrase() { tagObjects = new ArrayList<Tag>(); tags = new HashSet<String>(); } // getters and setters // … public void addTagObject(Tag t) { if (!getTagObjects().contains(t)) { getTagObjects().add(t); } if (!t.getPhrases().contains(this)) { t.getPhrases().add(this); } } public void addTag(String tagName) { if (!getTags().contains(tagName)) { getTags().add(tagName); } }
Tag.java
@Entity public class Tag { @Id @Column(name="uname") private String uniqueName; private String description; @ManyToMany(mappedBy="tagObjects") private Collection<Phrase> phrases; public Tag() { phrases = new ArrayList<Phrase>(); } // getters and setters // …
標記實體的主鍵是它的名字。我想保留Phrase.java
一個Set
與多對多關係的tagObjects
字段「同步」的標籤名稱,反之亦然。這樣做,我添加一個偵聽Phrase.java
:
public class PhraseListener {
@PostLoad
public void postLoad(Phrase p) {
System.out.println("In post load");
for (Tag tag : p.getTagObjects()) {
p.addTag(tag.getUniqueName());
}
}
@PrePersist
public void prePersist(Phrase p) {
System.out.println("In pre persist");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestJPA");
EntityManager em = emf.createEntityManager();
for (String tagName : p.getTags()) {
Tag t = em.find(Tag.class, tagName);
if (t == null) t = new Tag(tagName);
p.addTagObject(t);
}
}
}
其加載後,會創建一組來自標籤的物體標記名稱,並堅持它讀取組標籤名稱之前,並獲取或創建標籤對象。
我的問題是,如果我嘗試創建多個共享標記的短語,JPA不是僅創建關係(插入連接表),而是創建違反主鍵約束的標記對象。
transaction.begin();
Phrase p = new Phrase("Never ask what sort of computer a guy drives. If he's a Mac user, he'll tell you. If not, why embarrass him?", "Tom Clancy");
p.addTag("apple");
p.addTag("macintosh");
em.persist(p);
transaction.commit();
transaction.begin();
p = new Phrase("It's better to be a pirate than to join the Navy.", "Steve Jobs");
p.addTag("apple");
em.persist(p);
transaction.commit();
異常在線程 「主」 javax.persistence.RollbackException:異常[的EclipseLink-4002](Eclipse持久服務 - 2.5.0.v20130507-3faac2b):org.eclipse.persistence.exceptions.DatabaseException 內部異常:java.sql.SQLException:[SQLITE_CONSTRAINT]由於違反約束而中止(列uname不是唯一的) 錯誤代碼:0 調用:插入到標記(uname,DESCRIPTION)VALUES(?,?) bind = > [apple,null]
您可以查看是否JPA按預期工作?我有直覺認爲即使元素在數據庫中,em.find(Tag.class,tagName)也會返回null。你可以調試嗎? –