java - 为什么 Hibernate 会在我每次运行我的应用程序时插入重复记录?

标签 java hibernate orm configuration duplicates

使用 Hibernate 4.2.3 final。我有以下实体:

@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 不在多个驱动程序运行中插入重复项?

最佳答案

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

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

关于java - 为什么 Hibernate 会在我每次运行我的应用程序时插入重复记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19965370/

相关文章:

java - 什么时候在 Java 中创建的本地引用中声明和初始化对象?

Javax空整数字段验证

java - JPA/Hibernate 中的孤儿和 child 处理

java - Hibernate 是否支持并发获取数据?

python - Flask-SqlAlchemy 邻接列表关系 backfref 意外错误

java - 为什么我不能使用 JMockit 模拟数学

java - 从 JScrollPane 中删除边框

java - KStream从一个集群到多个集群

java - Spring + Hibernate DAO 作为泛型类

architecture - ZF2 Skeleton 和 Doctrine ORM xml 模式合并