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

ash*_*hur 10 java sql oracle jpa java-ee

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

不幸的是我得到了

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

我使用上述方法时的异常.我认为问题在于我的数据库已全部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();
    }   
}
Run Code Online (Sandbox Code Playgroud)

地址类

@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 + " ]";
    }

}
Run Code Online (Sandbox Code Playgroud)

kdo*_*teu 19

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

     <property name="eclipselink.allow-zero-id" value="true"/>
Run Code Online (Sandbox Code Playgroud)

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

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

  • 谢谢.这是我正在寻找的确切解决方案.我有@Camilo Bermudez建议的内容(GeneratedValue注释)但是我在ID = 0的数据库中添加了一个用户后,我开始得到这个错误. (2认同)
  • 此属性现已弃用。使用`&lt;property name="eclipselink.id-validation" value="NULL"/&gt;` (2认同)

Cam*_*ilo 6

您需要使用@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;
Run Code Online (Sandbox Code Playgroud)

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

检查上面链接中的文档。