Por que o Hibernate está inserindo registros duplicados toda vez que eu executo meu aplicativo?

Usando o Hibernate 4.2.3 final. Eu tenho a seguinte entidade:

@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 synonyms; @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "antonyms", joinColumns = @JoinColumn(name = "word_id"), inverseJoinColumns = @JoinColumn(name = "antonym_id")) private List antonyms; // ctor, getters/setters, etc. } 

E o seguinte DAO para a entidade:

 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; } } 

E o seguinte driver de teste:

 public class HibernateTester { public static void main(String[] args) { Word fast = new Word("fast", 4, WordType.Adverb, "A fast thing.", new ArrayList(), new ArrayList()); Word slow = new Word("slow", 4, WordType.Adverb, "A slow thing.", new ArrayList(), new ArrayList()); Word quick = new Word("quick", 5, WordType.Adverb, "A quick thing.", new ArrayList(), new ArrayList()); quick.addSynonym(fast); quick.addAntonym(slow); WordDAO wordDAO = new WordDAO(); wordDAO.saveWord(quick); } } 

Se eu rodar o HibernateTester várias vezes, ele insere as 3 palavras nas minhas tabelas DB a cada vez. Portanto, se eu excluir todos os registros da minha tabela de words e, em seguida, executar o driver de teste 4 vezes, terei 12 palavras na tabela (4 execuções x 3 registros / executar). Como estou usando o Session#saveOrUpdate , eu esperaria que o Hibernate fosse inteligente o bastante para descobrir que as entidades já existiam no database e impedi-las de serem inseridas.

Assim:

  1. Por que isso está acontecendo?; e mais importante
  2. O que é uma solução viável? Como configuro o Hibernate para não inserir dupes em várias execuções de driver?

Desde já, obrigado!