在工作单元克隆中遇到JPA Null或零主键

时间:2014-02-25 21:33:40

标签: java sql oracle java-ee jpa

我了解JPA并负责制作数据库并为其插入一些值。我想知道如何找出最近插入的对象的ID是什么,所以我找到了一种方法,我需要使用flush的{​​{1}}方法。

不幸的是我得到了

  

工作单元克隆中遇到空或零主键

我使用上述方法时出现

异常。我认为问题在于我的数据库已经将所有EntityManager设置为自动增量(我使用ORACLE 11G Express ),因此在提交之前它具有ID's值并且它回滚事务。

我可以做些什么来修复它?

这是DB(ID是自动增量[oracle中的序列和触发器]):

null
  

地址类

public class Client {    
    public static void main(String[] args) {
        EntityManagerFactory emf =
                Persistence.createEntityManagerFactory("JpaIntroductionPU");        
        EntityManager em = emf.createEntityManager();
        EntityTransaction et = em.getTransaction();

        et.begin();

        Address ad1 = new Address();
        ad1.setStreet("Skaraktki");
        ad1.setCode("64-340");

        em.persist(ad1);
        em.flush();

        System.out.println(ad1.getAId());
        et.commit();
    }   
}

3 个答案:

答案 0 :(得分:18)

这发生在我身上,因为我手动将一个条目添加到我的数据库,其id为0(零)。 在我的情况下,EclipseLink“无法”处理一个零的id。 所以我在persistence.xml中添加了以下内容:

     <property name="eclipselink.allow-zero-id" value="true"/>

此属性表示EclipseLink将零作为有效ID处理。

[1] http://meetrohan.blogspot.de/2011/11/eclipselink-null-primary-key.html

答案 1 :(得分:5)

您需要使用@GeneratedValue注释您的ID字段,以便JPA知道数据库会自动生成ID:

@Id
@Basic(optional = false)
@Column(name = "A_ID")
@SequenceGenerator( name = "mySeq", sequenceName = "MY_SEQ", allocationSize = 1, initialValue = 1 )
@GeneratedValue(strategy=GenerationType.IDENTITY, generator="mySeq")
private BigDecimal aId;

使用oracle,您可以使用GenerationType.IDENTITY@SequenceGenerator,在这种情况下,您不需要触发器来查询序列并填充ID,JPA将为您执行此操作。我不确定GenerationType.AUTO是否可以与oracle一起使用,但如果确实如此,则需要触发器来查询序列并填充id。 GenerationType.TABLE是最便携的解决方案,因为您使用由JPA管理的独立表来存储序列,它适用于所有数据库。

检查上面链接中的文档。

答案 2 :(得分:0)

正如您所说,问题在于即使您提交事务,也不会立即调用自动增量函数。实际上,当您使用同一个 EntityManager 管理数据库交互时,它不会。 我的问题是:你为什么要坚持,然后如果你刷新它就提交事务?对我来说看起来像重复的代码。 见 this 同花顺。