Java – JPA encountered null or zero primary key in unit of work cloning

I understand JPA and have the task of creating a database and inserting some values for it I want to know how to find out the ID of the recently inserted object, so I found a method. I need to use the flush method of entitymanager

Unfortunately, I got it

Exceptions when I use the above method I think the problem is that my database has all IDS set on automatic increment (I use Oracle 11g express), so it has a null value before committing and it rolls back the transaction

What can I do to fix it?

This is dB (ID is auto increment [sequence and trigger in 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 + " ]";
    }

}

Solution

You need to annotate your ID field with @ generatedvalue so that JPA knows that DB will automatically generate 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;

With Oracle, you can use generationtype Identity and @ sequencegenerator. In this case, you don't need a trigger to query the sequence and fill in the ID. JPA will do this for you I'm not sure about generationtype Whether auto can be used with Oracle, but if so, you need a trigger to query the sequence and fill in ID. generationtype Table is the most portable solution because you use a separate table managed by JPA to store sequences, which is applicable to all databases

Check the document in the link above

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>