我目前正在尝试使用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);
答案 0 :(得分:1)
Hibernate没有得到具有相同name
的实体应该是同一个实体。您将级联类型设置为CascadeType.ALL
,这使得Hibernate在遇到没有分配ID的实体时插入新实体。
我建议:
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
中