Why is Hibernate inserting duplicate records every time I run my app?

倖福魔咒の 提交于 2019-12-08 05:57:22

问题


Using Hibernate 4.2.3 final. I have the following entity:

@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.
}

And the following DAO for the entity:

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

And the following test driver:

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

If I run HibernateTester multiple times, I it inserts the 3 words into my DB tables each time. So if I delete every record from my words table, and then run the test driver 4 times, I'll have 12 words in the table (4 runs x 3 records/run). Since I'm using Session#saveOrUpdate, I would have expected Hibernate to be smart enough to figure out that the entities already exist in the DB, and prevent them from being inserted.

So:

  1. Why is this happening?; and more importantly
  2. What is a viable solution? How do I configure Hibernate not to insert dupes across multiple driver runs?

Thanks in advance!


回答1:


saveOrUpdate() saves the entity if it doesn't have an ID, and updates it if it already has an ID. You always pass entities which don't have an ID, so Hibernate creates the entity. every time.

The only thing that identifies an entity is its ID. Not its name, text, or whatever other attribute.



来源:https://stackoverflow.com/questions/19965370/why-is-hibernate-inserting-duplicate-records-every-time-i-run-my-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!