最终使用 Hibernate 4.2.3。我有以下实体:
@Entity
@AttributeOverrides({
@AttributeOverride(name="id", column=@Column(name="word_id"))
})
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name="words")
public class Word {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
protected Long id;
@Column(name="word_text")
private String text;
@Column(name="word_length")
private Integer length;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="word_type_id", referencedColumnName="word_type_id")
private WordType type;
@Column(name="word_definition")
private String definition;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "synonyms", joinColumns = @JoinColumn(name = "word_id"), inverseJoinColumns = @JoinColumn(name = "synonym_id"))
private List<Word> synonyms;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "antonyms", joinColumns = @JoinColumn(name = "word_id"), inverseJoinColumns = @JoinColumn(name = "antonym_id"))
private List<Word> antonyms;
// ctor, getters/setters, etc.
}
以及该实体的以下 DAO:
public class WordDAO {
public Word saveWord(Word word) {
Session session = getDaoUtils().newSessionFactory().openSession();
Word returnable = null;
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.saveOrUpdate(word);
returnable = word;
transaction.commit();
} catch(Throwable throwable) {
transaction.rollback();
throw new RuntimeException(throwable);
} finally {
session.close();
}
// Return any result, if applicable.
return returnable;
}
}
以及以下测试驱动程序:
public class HibernateTester {
public static void main(String[] args) {
Word fast = new Word("fast", 4, WordType.Adverb, "A fast thing.", new ArrayList<Word>(), new ArrayList<Word>());
Word slow = new Word("slow", 4, WordType.Adverb, "A slow thing.", new ArrayList<Word>(), new ArrayList<Word>());
Word quick = new Word("quick", 5, WordType.Adverb, "A quick thing.", new ArrayList<Word>(), new ArrayList<Word>());
quick.addSynonym(fast);
quick.addAntonym(slow);
WordDAO wordDAO = new WordDAO();
wordDAO.saveWord(quick);
}
}
如果我HibernateTester
多次运行,我每次都会将 3 个单词插入我的数据库表中。因此,如果我从words
表中删除每条记录,然后运行测试驱动程序 4 次,表中将有 12 个单词(4 次运行 x 3 条记录/运行)。由于我使用的是Session#saveOrUpdate
,所以我希望 Hibernate 足够聪明,可以找出数据库中已经存在的实体,并阻止它们被插入。
为什么会这样?更重要的是,什么是可行的解决方案?如何将 Hibernate 配置为不在多个驱动程序运行中插入欺骗?