2015-04-21 25 views
1

我有以下Oracle表定義。如何使用@ID和@GeneratedValue從Hibernate + JPA中的序列獲取Oracle生成的值

CREATE TABLE "SIAS"."OPERATION_REG" 
    (
    "ID"    NUMBER CONSTRAINT "CT_OPERATION_REG_ID" NOT NULL ENABLE, 
    "OPERATION_NAME" VARCHAR2(30 BYTE), 
    "APPLICATION_NAME" VARCHAR2(30 BYTE), 
    "EXECUTION_DATE" DATE, 
    "EXECUTION_USER" VARCHAR2(80 BYTE), 
    "RESULT"   VARCHAR2(20 BYTE), 
    CONSTRAINT "PK_OPERATION_REG_ID" PRIMARY KEY ("ID") USING INDEX PCTFREE 10 
    INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOLOGGING STORAGE(INITIAL 65536 NEXT 
    1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST 
    GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) 
    TABLESPACE "SIAS_DAT" ENABLE 
) 
    SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
    NOCOMPRESS LOGGING STORAGE 
    (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 
    0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT 
    CELL_FLASH_CACHE DEFAULT 
) 
    TABLESPACE "SIAS_DAT" ; 
CREATE UNIQUE INDEX "SIAS"."IDX_OPERATION_REG_ID" ON "SIAS"."OPERATION_REG" 
    (
    "ID" 
) 
    PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS NOLOGGING STORAGE 
    (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 
    FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT 
    CELL_FLASH_CACHE DEFAULT 
) 
    TABLESPACE "SIAS_DAT" ; 
CREATE OR REPLACE TRIGGER "SIAS"."BI_OPERATION_REG" BEFORE 
    INSERT ON OPERATION_REG REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW BEGIN 
    :NEW.ID := SEQ_OPERATION_REG.NEXTVAL; 
EXCEPTION 
WHEN OTHERS THEN 
    RAISE_APPLICATION_ERROR 
    (
    -20255, 'ERROR EN TRIGGER BI_OPERATION_REG' 
) 
    ; 
END; 
/
ALTER TRIGGER "SIAS"."BI_OPERATION_REG" ENABLE; 

我有這樣的觸發啓用自動生成ID列的值正在創建一個新的行時。

create or replace 
TRIGGER BI_OPERATION_REG BEFORE INSERT 
    ON OPERATION_REG 
    REFERENCING NEW AS NEW OLD AS OLD 
    FOR EACH ROW 
BEGIN 
    :NEW.ID   := SEQ_OPERATION_REG.NEXTVAL; 
EXCEPTION 
    WHEN OTHERS 
    THEN 
     RAISE_APPLICATION_ERROR (-20255, 'ERROR EN TRIGGER BI_OPERATION_REG'); 
END; 

這是序列定義來生成ID值

CREATE SEQUENCE "SIAS"."SEQ_OPERATION_REG" MINVALUE 1 MAXVALUE 
999999999999999999999999999 INCREMENT BY 1 START WITH 37 NOCACHE NOORDER NOCYCLE ; 

我在數據庫中沒有控制,因爲DBA團隊是我的範圍,所以我要處理與這些定義。我創建了映射OPERATION_REG表的JPA實體。這是列ID的ID屬性方法映射。

@Id 
@GeneratedValue(strategy = GenerationType.AUTO, generator = "G1") 
@SequenceGenerator(name = "G1", sequenceName = "SEQ_OPERATION_REG") 
@Column(name = "ID") 
public int getId() { 
    return id; 
} 

這是我的實體映射的全部代碼

import org.hibernate.annotations.GenericGenerator; 

    import javax.persistence.*; 
    import java.sql.Timestamp; 
    import java.util.Collection; 

    @Entity 
    @Table(name = "OPERATION_REG") 
    public class OperationRegEntity extends BaseEntity { 
     private int id; 
     private String operationName; 
     private String applicationName; 
     private Timestamp executionDate; 
     private String executionUser; 
     private String result; 
     private Collection<TokenRegEntity> tokenRegsById; 
     private Collection<TraceRegEntity> traceRegsById; 

     @Id 
     @GeneratedValue(generator="select-generator") 
     @GenericGenerator(name="select-generator", strategy="select", parameters = @org.hibernate.annotations.Parameter(name="key", value="ID")) 
    // @GeneratedValue(strategy = GenerationType.AUTO, generator = "G1") 
    // @SequenceGenerator(name = "G1", sequenceName = "SEQ_OPERATION_REG") 
     @Column(name = "ID") 
     public int getId() { 
      return id; 
     } 

     public void setId(int id) { 
      this.id = id; 
     } 

     @Basic 
     @Column(name = "OPERATION_NAME") 
     public String getOperationName() { 
      return operationName; 
     } 

     public void setOperationName(String operationName) { 
      this.operationName = operationName; 
     } 

     @Basic 
     @Column(name = "APPLICATION_NAME") 
     public String getApplicationName() { 
      return applicationName; 
     } 

     public void setApplicationName(String applicationName) { 
      this.applicationName = applicationName; 
     } 

     @Basic 
     @Column(name = "EXECUTION_DATE") 
     public Timestamp getExecutionDate() { 
      return executionDate; 
     } 

     public void setExecutionDate(Timestamp executionDate) { 
      this.executionDate = executionDate; 
     } 

     @Basic 
     @Column(name = "EXECUTION_USER") 
     public String getExecutionUser() { 
      return executionUser; 
     } 

     public void setExecutionUser(String executionUser) { 
      this.executionUser = executionUser; 
     } 

     @Basic 
     @Column(name = "RESULT") 
     public String getResult() { 
      return result; 
     } 

     public void setResult(String result) { 
      this.result = result; 
     } 

     @Override 
     public boolean equals(Object o) { 
      if (this == o) return true; 
      if (o == null || getClass() != o.getClass()) return false; 

      OperationRegEntity that = (OperationRegEntity) o; 

      if (id != that.id) return false; 
      if (applicationName != null ? !applicationName.equals(that.applicationName) : that.applicationName != null) 
       return false; 
      if (executionDate != null ? !executionDate.equals(that.executionDate) : that.executionDate != null) 
       return false; 
      if (executionUser != null ? !executionUser.equals(that.executionUser) : that.executionUser != null) 
       return false; 
      if (operationName != null ? !operationName.equals(that.operationName) : that.operationName != null) 
       return false; 
      if (result != null ? !result.equals(that.result) : that.result != null) return false; 

      return true; 
     } 

     @Override 
     public int hashCode() { 
      int result1 = id; 
      result1 = 31 * result1 + (operationName != null ? operationName.hashCode() : 0); 
      result1 = 31 * result1 + (applicationName != null ? applicationName.hashCode() : 0); 
      result1 = 31 * result1 + (executionDate != null ? executionDate.hashCode() : 0); 
      result1 = 31 * result1 + (executionUser != null ? executionUser.hashCode() : 0); 
      result1 = 31 * result1 + (result != null ? result.hashCode() : 0); 
      return result1; 
     } 

     @OneToMany(mappedBy = "operationRegByOperationRegId") 
     public Collection<TokenRegEntity> getTokenRegsById() { 
      return tokenRegsById; 
     } 

     public void setTokenRegsById(Collection<TokenRegEntity> tokenRegsById) { 
      this.tokenRegsById = tokenRegsById; 
     } 

     @OneToMany(mappedBy = "operationRegByOperationRegId") 
     public Collection<TraceRegEntity> getTraceRegsById() { 
      return traceRegsById; 
     } 

     public void setTraceRegsById(Collection<TraceRegEntity> traceRegsById) { 
      this.traceRegsById = traceRegsById; 
     } 
    } 

我有一個問題,因爲,當我創建一個新對象,並堅持它的數據庫上,我遵循這個策略

@Autowired 
OperationRegService operationregservice; 

@Transactional(propagation = Propagation.REQUIRES_NEW) 
public OperationRegEntity createOperationReg(GenericRequestParameters parameters) { 
    OperationRegEntity oper = new OperationRegEntity(); 
    oper.setApplicationName(parameters.getApplication()); 
    oper.setExecutionUser(parameters.getApplicationUser()); 
    oper.setOperationName(parameters.getSIASOperationName()); 
    oper.setExecutionDate(new Timestamp(Calendar.getInstance().getTime().getTime())); 
    oper.setResult("INITIATED"); 
    operationregservice.persist(oper); 
    return oper; 
} 

當我分析oper.getID()的信息時,該值與數據庫中創建的實際值不同,特別是始終低於1點。例如,Java實體的ID值爲,錶行實體的ID值爲,就好像該序列被調用兩次。有任何想法嗎?

回答

0

好吧,我想不通的問題,這是在觸發產生的序列的方式。關鍵是要生成序列如果沒有設置ID值。這樣,Hibernate將調用序列,設置ID值,並且觸發器將檢查值是否已設置,如果是,則不調用序列。如果沒有設置值,則觸發調用序列,並將其值

這是有效的觸發

create or replace 
TRIGGER BI_OPERATION_REG BEFORE INSERT 
    ON OPERATION_REG 
    REFERENCING NEW AS NEW OLD AS OLD 
FOR EACH ROW 
BEGIN 
    IF :NEW.ID IS NULL THEN SELECT SEQ_OPERATION_REG.NEXTVAL INTO :NEW.ID FROM dual; END IF; 
EXCEPTION 
    WHEN OTHERS 
    THEN 
     RAISE_APPLICATION_ERROR (-20255, 'ERROR EN TRIGGER BI_OPERATION_REG'); 
END;    
2

您不應該使用@SequenceGenerator,因爲當您希望Hibernate在持久化實體時調用序列時會使用它。

在您的使用情況下,數據庫不通話,所以你需要使用select identifier generator strategy

@Id 
@GeneratedValue(generator="select-generator") 
@GenericGenerator(name="select-generator", 
    strategy="select", 
    parameters = @org.hibernate.annotations.Parameter(name="key", value="ID") 
) 
@Column(name = "ID") 
public int getId() { 
    return id; 
} 
+0

有什麼根據您的回覆不見了?我複製粘貼它,然後用_ @ Parameter(name =「key」,value =「ID」)_的部分獲得編譯錯誤。它說:_cannot解決方法**名稱** _ –

+0

請確保您使用預期的類類型。嘗試給它全班名(包括包) –

+0

好吧,這是一個命名空間包括的問題。我使用[email protected](name =「key」,value =「ID」))_但現在我在運行時遇到這個錯誤:_org.hibernate.MappingException:未知屬性:ID_ –

相關問題