为什么我的更新会抛出一个hibernate ConstraintViolationException?

时间:2014-10-17 16:20:53

标签: sql oracle hibernate jdbc

CREATE TABLE GUSERPRO
(
  USER_NAME      VARCHAR2(20 BYTE),
  SYSTEM         VARCHAR2(8 BYTE),
  PROCESS        VARCHAR2(8 BYTE),
  LOGIN_TIME     NUMBER,
  LOGIN_DATE     DATE,
  LOGOUT_TIME    NUMBER,
  LOGOUT_DATE    DATE,
  TOTAL_ELAPSED  NUMBER,
  TOTAL_LOGINS   NUMBER
)
TABLESPACE ERIP_D
PCTUSED    0
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MINEXTENTS       1
            MAXEXTENTS       2147483645
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
LOGGING 
NOCOMPRESS 
NOCACHE
NOPARALLEL
MONITORING
ENABLE ROW MOVEMENT;

异常堆栈引用此约束:

CREATE UNIQUE INDEX GUSERPRO_N1 ON GUSERPRO
(USER_NAME, SYSTEM, PROCESS)
LOGGING
TABLESPACE ERIP_D
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MINEXTENTS       1
            MAXEXTENTS       2147483645
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOPARALLEL;

尝试将记录更新到Oracle数据库时,我收到此错误,但并非总是如此,有些情况我得到此错误。如果我创建一个新记录然后更新它工作正常。如果我尝试更新现有记录,则会抛出此错误。 请帮我摆脱这个。

org.springframework.dao.DataIntegrityViolationException: 
   Could not execute JDBC batch update; 
   SQL [update PDOXDATA_GUSERPRO set PROCESS=?, SYSTEM=? where USER_NAME=?]; 
   constraint [PDOXDATA_GUSERPRO_N1]; 

nested exception is org.hibernate.exception.ConstraintViolationException: 
    Could not execute JDBC batch update
    << rest of error stack >>

以下是相关课程:

/**
 * 
 */
package com.lv.rs.accessautomation.common.vo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

/**
 * @author tp50148
 *
 */
@Entity
@Table(name="PDOXDATA_GUSERPRO"/*,uniqueConstraints = {@UniqueConstraint(columnNames = "userName")}*/)
public class EripUserProVO implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "USER_NAME")
    private String userName;

    @Column(name = "SYSTEM")
    private String system;

    @Column(name = "PROCESS")
    private String process;

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="USER_NAME")
    private List<EripGtSignatVO> eripGtSignatVO = new ArrayList<EripGtSignatVO>();

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="USER_NAME")
    private List<EripGUsersVO> eripGUsersVO = new ArrayList<EripGUsersVO>();

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="USERNAME")
    private List<EripUserLocationVO> eripUserLocationVO = new ArrayList<EripUserLocationVO>();

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="USER_USER")
    private List<Eripcpa95VO> eripcpa95VO = new ArrayList<Eripcpa95VO>();

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="USERNAME")
    private List<EriporaSacUserVO> eriporaSacUserVO = new ArrayList<EriporaSacUserVO>();

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
    @JoinColumn(name="SACUSER_USERNAME")
    private List<EriporaSacAccessVO> eriporaSacAccessVO = new ArrayList<EriporaSacAccessVO>();

    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getSystem() {
        return system;
    }
    public void setSystem(String system) {
        this.system = system;
    }
    public String getProcess() {
        return process;
    }
    public void setProcess(String process) {
        this.process = process;
    }
    public List<EripGtSignatVO> getEripGtSignatVO() {
        return eripGtSignatVO;
    }
    public void setEripGtSignatVO(List<EripGtSignatVO> eripGtSignatVO) {
        this.eripGtSignatVO = eripGtSignatVO;
    }
    public List<EripGUsersVO> getEripGUsersVO() {
        return eripGUsersVO;
    }
    public void setEripGUsersVO(List<EripGUsersVO> eripGUsersVO) {
        this.eripGUsersVO = eripGUsersVO;
    }
    public List<EripUserLocationVO> getEripUserLocationVO() {
        return eripUserLocationVO;
    }
    public void setEripUserLocationVO(List<EripUserLocationVO> eripUserLocationVO) {
        this.eripUserLocationVO = eripUserLocationVO;
    }
    public List<Eripcpa95VO> getEripcpa95VO() {
        return eripcpa95VO;
    }
    public void setEripcpa95VO(List<Eripcpa95VO> eripcpa95vo) {
        eripcpa95VO = eripcpa95vo;
    }
    public List<EriporaSacUserVO> getEriporaSacUserVO() {
        return eriporaSacUserVO;
    }
    public void setEriporaSacUserVO(List<EriporaSacUserVO> eriporaSacUserVO) {
        this.eriporaSacUserVO = eriporaSacUserVO;
    }
    public List<EriporaSacAccessVO> getEriporaSacAccessVO() {
        return eriporaSacAccessVO;
    }
    public void setEriporaSacAccessVO(List<EriporaSacAccessVO> eriporaSacAccessVO) {
        this.eriporaSacAccessVO = eriporaSacAccessVO;
    }



}

1 个答案:

答案 0 :(得分:1)

  
    

“这个错误[...]反复出现在特定记录中。”

  

您可以识别可重复显示此行为的特定记录。所以这应该很容易调试。但是,让我们为你取消它。

根据错误堆栈,您的更新语句是:

update PDOXDATA_GUSERPRO 
set PROCESS=?, SYSTEM=? 
where USER_NAME=?

您的约束PDOXDATA_GUSERPRO_N1(USER_NAME, SYSTEM, PROCESS)上的复合唯一键。这些是更新语句中涉及的三列。 这不是巧合

唯一复合键强制执行唯一排列。因此,我们可以为同一个PROCESS或同一个SYSTEM或同一个USER_NAME设置多个行。对于USER_NAME,SYSTEM,PROCESS的任何排列,我们都不能有多行。

所以,这是一个预测:当你传入一个有多个记录的USER_NAME时,更新失败。在这种情况下,您尝试为同一USER_NAME的多个实例设置相同的PROCESS和SYSTEM,这就是您获得唯一约束违规的原因。


现在我们可以看到你的代码很清楚@Hurds是正确的,你的Hibernate配置与你的物理数据模型不匹配。您已定义了一个列ID而不是所有三列:

    @Id
    @Column(name = "USER_NAME")
    private String userName;

    @Column(name = "SYSTEM")
    private String system;

所以你可以选择:

  • 如果您的数据库错误,则需要删除并重新创建约束。显然,这将需要管理现有数据以删除具有多个密钥实例的记录。

  • 如果需要维护组合键,可以通过两种方法在Hibernate中配置它。 Check this other StackOverflow thread