1

最终使用 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 配置为不在多个驱动程序运行中插入欺骗?

4

1 回答 1

4

saveOrUpdate()如果实体没有 ID,则保存它,如果它已经有 ID,则更新它。你总是传递没有 ID 的实体,所以 Hibernate 会创建实体。每次。

唯一能识别实体的是它的 ID。不是它的名称、文本或任何其他属性。

于 2013-11-13T22:11:22.587 回答