Hibernate重复数据库条目

时间:2017-12-01 15:43:29

标签: java hibernate

我目前正在尝试使用Hibernate编辑我的第一个数据库。 我有两个表:testobject_typ和testobject。 测试对象具有测试对象类型。

问题是:当我将新测试对象写入数据库时​​,即使已存在具有匹配名称的条目,也会使用新ID创建新的测试对象类型。

如何阻止Hibernate创建新条目并使用具有相同名称的现有条目?

我的Java类看起来像这样:

@Entity
@Table(name = "testobject")
public class TestObject {

@Id
@Column(name="testobject_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(name = "mc_id")
private int mcid;

@Column(name = "name")
private String name;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="testobjecttyp_id")
private TestObjectTyp testObjectTyp;
@Entity
@Table(name = "testobject_typ")
public class TestObjectTyp {

@Id
@Column(name="testobjecttyp_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(name = "name")
private String name;

TestObjectService

@Override
public synchronized boolean addTestObject(TestObject testObject){
    if (testobjectDao.testObjectExists(testObject.getMcid())) {
        return false;
    } else {
        testobjectDao.addTestObject(testObject);
        return true;
    }
}

TestobjectDAO

public class TestobjectDao implements ITestobjectDao {
@PersistenceContext
private EntityManager entityManager;

@Override
public void addTestObject(TestObject testObject) {
    entityManager.persist(testObject);
}

@Override
public boolean testObjectExists(int mcid) {
    String hql = "FROM TestObject as to WHERE to.mcid = ?";
    int count = entityManager.createQuery(hql).setParameter(1, mcid).getResultList().size();
    return count > 0 ? true : false;
}

我如何创建实体:

TestObject testObject = new TestObject();
TestObjectTyp testobjectTyp = new TestObjectTyp(); 
testobjectTyp.setName(TestobjectTypes.specification); 
testObject.setTestObjectTyp(testobjectTyp);
testObject.setMcid(110);
testObject.setName("Test");
iDatabaseService.addTestObject(testObject);

2 个答案:

答案 0 :(得分:1)

Hibernate没有得到具有相同name的实体应该是同一个实体。您将级联类型设置为CascadeType.ALL,这使得Hibernate在遇到没有分配ID的实体时插入新实体。

我建议:

  • 检查实体是否存在同名(通过执行Hibernate查询,如select from TestObjectTyp where name = :name)。如果它不存在,请插入一个新的TestObjectTyp并改为使用它。
  • (可选)向name字段添加唯一约束,以防止存在同名对象。

其他替代方法是使用名称作为主键(而不是生成的ID),但使用具有任何含义的PK通常是不好的做法;)

答案 1 :(得分:1)

根据您的评论:

是的,如果你只是创建一个实体的新的istance然后保存它(在这种情况下通过级联),hibernate将在db中创建一个新行。

而不是

TestObjectTyp testobjectTyp = new TestObjectTyp(); 
testobjectTyp.setName(TestobjectTypes.specification); 

你应该查询db的那个TestObjectTyp

e.g。

"FROM TestobjectTypes tot WHERE tot.name = ?";

不同之处在于,现在hibernate知道这个TestobjectTypes(它被称为托管实体,意味着该实体上的更改将反映在db上),并且会知道它已经存在于db