Java EJB/JPA:持久化实体对象后,其getId()返回0,即使它';它已正确地存储在表中
这是我所问问题的简化版,希望更清晰 编辑:我在NetBeans中工作,持久性提供程序是Hibernate,下面是实际数据库表的一个映像(响应@xiumeteo): 基本上,我的问题是,当我持久化一个实体时,我会自动生成ID值,即使实体正确地保存到数据库中,正确的ID>0,entityManager似乎总是认为现在持久化的实体的ID为0。这会导致随后违反外键约束,但这里我只关注Id为(或者更确切地说,冒充为)0,因为这应该与问题的原因密切相关,事实上,它本身就是一个谜 我有一个简单的实体类Person:Java EJB/JPA:持久化实体对象后,其getId()返回0,即使它';它已正确地存储在表中,java,hibernate,jpa,ejb,Java,Hibernate,Jpa,Ejb,这是我所问问题的简化版,希望更清晰 编辑:我在NetBeans中工作,持久性提供程序是Hibernate,下面是实际数据库表的一个映像(响应@xiumeteo): 基本上,我的问题是,当我持久化一个实体时,我会自动生成ID值,即使实体正确地保存到数据库中,正确的ID>0,entityManager似乎总是认为现在持久化的实体的ID为0。这会导致随后违反外键约束,但这里我只关注Id为(或者更确切地说,冒充为)0,因为这应该与问题的原因密切相关,事实上,它本身就是一个谜 我有一个简单的实体类Per
@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对象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)方法本身做了它应该做的事情:它使用正确生成的ID将person p持久化到person表中
但是,在person对象被持久化之后,当我尝试获取该ID的值时,问题变得很明显;它仍然是0。因此,我从servlet调用create(p)方法,然后立即获取持久化对象的ID并将其打印到控制台,如下所示(注意:personRepo是会话bean的注入实例,其定义见上文):
最后一个println语句总是打印0作为p.getId()的值,而我希望它打印对应于实体的表行的ID值
在对类似问题的回答中,我读到对flush()的调用应该有帮助(这就是为什么我将它添加到上面的create方法中),但在我的例子中显然没有。如上所述,即使从create()方法(执行实际持久化)返回到调用servlet之后,Id字段仍然被指定为值为0。尽管如此,正如我所说,它是在数据库表PERSON中存储的,正确的ID大于0
那么如何让getId()函数返回真实的id呢?
(通过扩展,希望entityManager/容器也能“看到”真实的id值,这样实体就可以在不违反FK约束的情况下参与多对多关系。)尝试使用
session.save(p)
而不是entityManager.persist(p)
save()
将返回一个标识符,如果必须执行插入以获取标识符,则会立即执行此插入
或
刷新后尝试刷新实体,以重新读取该实体状态
entityManager.persist(p);
entityManager.flush();
entityManager.refresh(p);
您在本例中使用的是哪个数据库?持久性提供程序是Hibernate。实际的数据库是JavaDB/Derby(见问题本身中新附的图片。这是对@xiumeteo…的回应,只是为了不让你在黑暗中呵呵。我做了一项研究,发现并非所有的驱动程序/db都支持使用IDENTITY GenerationType自动刷新id。我仍在寻找你的特殊情况。你是否尝试使用AUTO而不是identity?@Holland在JPAAPI中没有
entityManager.save(p)
!
entityManager.persist(p);
entityManager.flush();
entityManager.refresh(p);