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

时间:2017-02-17 01:20:51

标签: java hibernate jpa ejb

这是我问过的一个简化的,希望更清晰的版本

编辑:我在NetBeans工作,持久化提供程序是Hibernate,这里是实际数据库表的图像(响应@xiumeteo):

enter image description here

基本上,我的问题是,当我持久化实体时,我会自动生成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约束。)

1 个答案:

答案 0 :(得分:-2)

尝试使用session.save(p)代替entityManager.persist(p)save()将返回一个标识符,如果必须执行INSERT以获取标识符,则此INSERT立即发生。

OR

尝试在刷新后刷新您的实体,以重新读取该实体状态。

entityManager.persist(p);
entityManager.flush();
entityManager.refresh(p);