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

我了解JPA并且有任务创建数据库并为其插入一些值。 我想知道如何找出最近插入的对象的ID是什么,所以我找到了一种方法,我需要使用EntityManager flush方法。

不幸的是我得到了

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

我使用上述方法时的exception。 我认为问题在于我的数据库在自动增量ID's设置了所有ID's我使用ORACLE 11G Express ),因此在提交之前它具有null值并且它回滚事务。

我能做些什么来修复它?

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

 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(); } } 

地址类

 @Entity @Table(name = "ADDRESS") @NamedQueries({ @NamedQuery(name = "Address.findAll", query = "SELECT a FROM Address a"), @NamedQuery(name = "Address.findByAId", query = "SELECT a FROM Address a WHERE a.aId = :aId"), @NamedQuery(name = "Address.findByStreet", query = "SELECT a FROM Address a WHERE a.street = :street"), @NamedQuery(name = "Address.findByCode", query = "SELECT a FROM Address a WHERE a.code = :code")}) public class Address implements Serializable { private static final long serialVersionUID = 1L; // @Max(value=?) @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation @Id @Basic(optional = false) @Column(name = "A_ID") private BigDecimal aId; @Basic(optional = false) @Column(name = "STREET") private String street; @Basic(optional = false) @Column(name = "CODE") private String code; @OneToOne(cascade = CascadeType.ALL, mappedBy = "aId") private Employee employee; @OneToOne(cascade = CascadeType.ALL, mappedBy = "aId") private Department department; public Address() { } public Address(BigDecimal aId) { this.aId = aId; } public Address(BigDecimal aId, String street, String code) { this.aId = aId; this.street = street; this.code = code; } public BigDecimal getAId() { return aId; } public void setAId(BigDecimal aId) { this.aId = aId; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } @Override public int hashCode() { int hash = 0; hash += (aId != null ? aId.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Address)) { return false; } Address other = (Address) object; if ((this.aId == null && other.aId != null) || (this.aId != null && !this.aId.equals(other.aId))) { return false; } return true; } @Override public String toString() { return "jpaintroduction.Address[ aId=" + aId + " ]"; } } 

您需要使用@GeneratedValue注释您的id字段,以便JPA知道DB将自动生成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管理的独立表来存储序列,它适用于所有数据库。

检查上面链接中的文档。

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

   

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

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