Java EJB/JPA:持久化实体对象后,其getId()返回0,即使它';它已正确地存储在表中

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

这是我所问问题的简化版,希望更清晰

编辑:我在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对象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);