Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么Hibernate每次运行我的应用时都要插入重复记录?_Java_Hibernate_Orm_Configuration_Duplicates - Fatal编程技术网

Java 为什么Hibernate每次运行我的应用时都要插入重复记录?

Java 为什么Hibernate每次运行我的应用时都要插入重复记录?,java,hibernate,orm,configuration,duplicates,Java,Hibernate,Orm,Configuration,Duplicates,使用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(stra

使用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.
}
以及以下测试驱动程序:

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{
公共静态void main(字符串[]args){
单词fast=新词(“fast”,4,WordType.副词,“一个快速的东西”,new ArrayList(),new ArrayList());
单词slow=新词(“slow”,4,WordType.副词,“一个慢的东西”,new ArrayList(),new ArrayList());
单词quick=新词(“quick”,5,WordType.副词,“一件快的事情”,new ArrayList(),new ArrayList());
addSynonym(fast);
快。加反义词(慢);
WordDAO WordDAO=新的WordDAO();
saveWord(快速);
}
}
如果我多次运行
HibernateTester
,每次都会将这3个字插入数据库表中。因此,如果我从
words
表中删除每条记录,然后运行测试驱动程序4次,那么表中就有12个字(4次运行x 3次记录/运行)。因为我使用的是
会话#saveOrUpdate
,所以我希望Hibernate足够聪明,能够找出数据库中已经存在的实体,并防止它们被插入

因此:

  • 为什么会这样?;更重要的是
  • 什么是可行的解决方案?如何配置Hibernate,使其不在多个驱动程序运行中插入重复
  • 提前谢谢

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

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

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



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

    谢谢@JBNizet(+1)-那么这里的解决方案是什么?添加一个DAO方法,如
    WordDAO#getWordByText(String
    ),然后首先查找每个单词?这样每个单词都会有一个ID,所以当我去保存它时,它会被视为一个更新。。。这是一个可行的解决方案吗?这里的标准做法是什么?再次感谢!你应该做什么取决于你想要实现什么。你想实现什么?我想确保被骗者不会进入我的数据库。
    words
    表应该对
    word\u text
    word\u type\u id
    具有唯一性约束。因此,如果我想从数据库中提取一个单词,那么我想我必须有这样一个方法:
    WordDAO#getWord(String-wordText,WordType-WordType):word
    ,它可以这样调用:
    word-fox=WordDAO.getWord(“fox”,WordType.noon)。此时,
    fox
    应该有一个填充的ID,如果我对它进行任何更改(或不更改),然后调用
    wordDAO.saveWord(fox)
    ,那么它应该被更新,而不是插入……这是我能想到的最好的解决方案,但这是我的第一个Hibernate项目。所以我不确定是否有更好的方法来防止重复…这就是解决方法。但是,在数据库中还应该有一个惟一的约束,以在数据库级别强制执行该约束(这是唯一能够保证惟一性的约束)。注意,您不需要调用WordDAO.saveWord(fox)。对附加实体所做的任何更改都将自动保持不变,而无需调用任何保存方法。您只需在数据库中找到实体,并对其进行更新即可。谢谢@JBNizet(+1)-那么这里的解决方案是什么?添加一个DAO方法,如
    WordDAO#getWordByText(String
    ),然后首先查找每个单词?这样每个单词都会有一个ID,所以当我去保存它时,它会被视为一个更新。。。这是一个可行的解决方案吗?这里的标准做法是什么?再次感谢!你应该做什么取决于你想要实现什么。你想实现什么?我想确保被骗者不会进入我的数据库。
    words
    表应该对
    word\u text
    word\u type\u id
    具有唯一性约束。因此,如果我想从数据库中提取一个单词,那么我想我必须有这样一个方法:
    WordDAO#getWord(String-wordText,WordType-WordType):word
    ,它可以这样调用:
    word-fox=WordDAO.getWord(“fox”,WordType.noon)。此时,
    fox
    应该有一个填充的ID,如果我对它进行任何更改(或不更改),然后调用
    wordDAO.saveWord(fox)
    ,那么它应该被更新,而不是插入……这是我能想到的最好的解决方案,但这是我的第一个Hibernate项目。所以我不确定是否有更好的方法来防止重复…这就是解决方法。但是,在数据库中还应该有一个惟一的约束,以在数据库级别强制执行该约束(这是唯一能够保证惟一性的约束)。注意,您不需要调用WordDAO.saveWord(fox)。对附加实体所做的任何更改都将自动保持不变,而无需调用任何保存方法。您只需在数据库中找到实体,并对其进行更新,仅此而已。对于JB Nizet的进一步解释,您可以通过放弃自动生成的ID并声明由文本和类型字段组成的复合ID来防止这种情况。请参见:哎哟,不要这样做。太可怕了。总是喜欢纯技术的、自动生成的主键。它们使一切变得更容易、更清洁、更快。但这是一个可行的解决方案吗?这完全取决于你所说的可行。逐个重命名1000个文件是一个可行的解决方案,但在脚本中自动化任务是一种更好的方法。功能性PK不好。复合的、功能性的PK甚至更糟糕。它们不是我倾向于使用的东西。如果明天是办公室里又一个安静的日子,那就为明天读点书吧!“宗教战争已经结束
    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);
        }
    }