JPA:@SequenceGenerator未生成序列。

3

我的应用程序使用了Hibernate供应商的JPA和Oracle 11G数据库。

在我的MST_EMP表中,我使用以下本地查询:

  Query query  = this.entityManager.createNativeQuery("INSERT  INTO MST_EMP emp (" +
                    "EMP_NAME,EMP_MAIL_ID) VALUES ('dasdas',?)");
            query.setParameter(1,"dhrumil");
            query.executeUpdate();          

这里是我的MST_EMP实体详细信息...
@Table(name = "MST_EMP")
public class MstEmp implements Serializable, IsEntity {

    private static final long serialVersionUID = 1L;

    @Id 
    @Column(name = "EMP_CODE")
    @SequenceGenerator( name = "EMP_CODE_SEQ", sequenceName = "EMP_CODE_SEQ")   
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EMP_CODE_SEQ")
    private String empCode;


    @Column(name="EMP_MAIL_ID")
    private String empMailId;


    @Column(name="EMP_NAME")
    private String empName;

    public MstEmp() {
    }

    public String getEmpCode() {
        return this.empCode;
    }

    public void setEmpCode(String empCode) {
        this.empCode = empCode;
    }

    public String getCreatedBy() {
        return this.createdBy;
    }


    public void setEmpMailId(String empMailId) {
        this.empMailId = empMailId;
    }



    public String getEmpName() {
        return this.empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

}

据我理解,在本地查询中我们不需要给EMP_CODE赋值,因为序列与其相关联。
但是这个查询会给我返回以下错误信息...
SEVERE: ORA-01400: cannot insert NULL into ("PERK"."MST_EMP"."EMP_CODE")

SEVERE: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute native bulk manipulation query
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1179)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1112)

请问,我们在本地查询中需要提供EMP_CODE吗?

本地查询是否会自动引用实体中声明的序列?

谢谢。


为什么在处理如此微不足道的任务时需要使用本地查询? - Hasan Ceylan
1个回答

2

只有在通过EntityManager.persist()方法持久化新对象时,JPA才会自动生成序列:

例如:

EntityManager em = \\ ...  Initialise
MstEmp newMstEmp = new MstEmp();
newMstEmp.setEmpCode(...);
newMstEmp.setEmpMailId(...);
newMstEmp.setEmpName(...);
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(newMstEmp);
tx.commit();

当您直接向数据库应用JPQL(通过entityManager.createQuery())或直接向数据库应用原始SQL(通过entityManager.createNativeQuery(),就像此处所做的一样),您必须插入自己的序列:
Query query  = this.entityManager.createNativeQuery("INSERT  INTO MST_EMP emp (" +
                    "EMP_CODE,EMP_NAME,EMP_MAIL_ID) VALUES (EMP_CODE_SEQ.nextval,'dasdas',?)");
query.setParameter(1,"dhrumil");
query.executeUpdate();

谢谢您的回复。在您的建议下,我手动在本地查询中添加了序列ID。我在本地查询中使用了SEQUENCE_NAME.nextvalue,它运行良好。 - Gunjan Shah
这是最佳实践。在JPA中,为了减少数据库往返次数,通常使用allocationSize生成序列。如果您手动获取下一个序列,则会创建大的ID窗口。 - Hasan Ceylan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接