这是我问过的一个简化的,希望更清晰的版本
编辑:我在NetBeans工作,持久化提供程序是Hibernate,这里是实际数据库表的图像(响应@xiumeteo):基本上,我的问题是,当我持久化实体时,我会自动生成ID值,即使实体已正确保存到数据库中,但ID值正确> 0,entityManager似乎总是认为现在持久化的实体的ID为0.这导致后续违反外键约束,但在这里我只关注Id(或者更确切地说,冒充为)0,因为这应该与问题的原因密切相关,事实上它本身就是一个谜。
所以我有一个简单的实体类Person:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, unique = true)
private Long id; // I’ve also tried types Integer and int, doesn’t make a difference.
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
public Person() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// setters and getters for the other fields omitted here.
}
然后我有一个会话bean,包含一个方法create(p),它持久存在一个person-object p:
@Stateless
@Default
public class PersonRepositoryImpl implements PersonRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional // Deleting this annotation makes no difference, only added
it because I thought it might solve the problem...
public Person create(Person p) {
entityManager.persist(p);
entityManager.flush(); // Again, only added this statement because I thought it
might solve the issue, which it did not.
return p;
}
}
现在,create(p)方法本身就可以完成它应该做的事情:它将人员p保存到PERSON表中,并使用正确生成的ID。
然而,当我试图在 之后获取该ID 的值时,问题变得明显;它仍然被赋予为0.所以我从servlet调用create(p)方法,然后立即获取持久化对象的ID并将其打印到控制台,如下所示(注意:personRepo是会话bean的注入实例)其定义见上文):
Person p = new Person();
p.setName("Carl"); p.setEmail(carl@carl.nl);
p = personRepo.create(p); // Everything going fine here => entity p gets stored
in the PERSON table with a correctly generated ID>0.
System.out.println("The newly persisted entity now has the following ID: " + p.getId());
最后一个println语句总是打印0作为p.getId()的值,而我希望它打印对应于该实体的表行的ID值。
在对类似问题的回答中,我已经读过对flush()的调用应该有帮助(这就是为什么我将它添加到上面的create-method中),但显然在我的情况下它没有。如上所示,即使从create()方法(执行实际持久化)返回到调用servlet之后,Id-field仍然被赋予值为0.尽管如我所说,它就是在那里存储在具有正确ID> 0的数据库表PERSON中的点。
那么如何让getId()函数返回REAL id? (并且希望通过扩展,让entityManager /容器“看到”真实的id值,这样实体就可以参与多对多关系,而不会违反FK约束。)
答案 0 :(得分:-2)
尝试使用session.save(p)
代替entityManager.persist(p)
。 save()
将返回一个标识符,如果必须执行INSERT以获取标识符,则此INSERT立即发生。
OR
尝试在刷新后刷新您的实体,以重新读取该实体状态。
entityManager.persist(p);
entityManager.flush();
entityManager.refresh(p);