我了解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();
}
}
答案 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 同花顺。