2016-05-18 41 views
0

我試圖使用序列爲DB2中的表生成增量ID。它將SQL語句直接發送到數據庫時有效,但在使用ebean時,語句失敗。以下是一個Java領域:Ebean註解 - 在DB2中使用序列生成ID

@Id 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TABLENAME_IDNAME_TRIG") 
@SequenceGenerator(name = "TABLENAME_IDNAME_TRIG", sequenceName = "TABLENAME_IDNAME_SEQ") 
@Column(name = "IDNAME") 
private Long id; 

下面是SQL列(蟾蜍):

Name   Data type Not Null Default Generated Bit Data Scope Identity  
IDNAME   INTEGER  Yes        No     No 

下面是在SQL序列定義:

CREATE OR REPLACE SEQUENCE SCHEMA.TABLENAME_IDNAME_SEQ 
    AS INTEGER CACHE 50 ORDER; 

和觸發:

CREATE OR REPLACE TRIGGER SCHEMA.TABLENAME_IDNAME_TRIG 
    NO CASCADE BEFORE INSERT 
    ON TABLENAME 
    REFERENCING 
    NEW AS OBJ 
    FOR EACH ROW 
BEGIN 
    SET obj.IDNAME=NEXT VALUE FOR SCHEMA.TABLENAME_IDNAME_SEQ; 
END; 

我的問題是什麼註釋在這裏?作爲一個(重要的)附註 - 當我將GenerationType設置爲AUTO,TABLE或IDENTITY時,它可以工作,即使它不應該,因爲我也使用這個對象來表示並行oracle表,它也使用序列ID生成。

編輯,包括錯誤消息:

javax.persistence.PersistenceException: Error getting sequence nextval 
... 
Caused by: com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-348, SQLSTATE=428F9, SQLERRMC=NEXTVAL FOR SCHEMA.TABLENAME_IDNAME_SEQ, DRIVER=4.19.49 

編輯2:發生故障的具體的SQL語句是:

values nextval for QA_CONNECTION_ICONNECTIONI_SEQ union values nextval for QA_CONNECTION_ICONNECTIONI_SEQ union values nextval for QA_CONNECTION_ICONNECTIONI_SEQ 

這是由Ebean生成的SQL。這是真實陳述的一個較小版本,它重複了20次,所以我在猜測生成緩存查詢時遇到的問題。編輯3:我相信這可能是Ebean使用DB2序列時的一個錯誤。這個函數生成SQL與DB2

public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) { 
    super(be, ds, seqName, batchSize); 
    this.baseSql = "values nextval for " + seqName; 
    this.unionBaseSql = " union " + baseSql; 
} 

EDIT 4時,我會返回一個錯誤:基於這個SO環節我認爲這是一個錯誤上。 Can't insert multiple values into DB2 by using UNION ALL and generate IDs from sequence 正確的類可能看起來像這樣?雖然我從未嘗試建造圖書館,所以我無法測試它。我猜,該學習如何打開缺陷了。

public class DB2SequenceIdGenerator extends SequenceIdGenerator { 

    private final String baseSql; 
    private final String unionBaseSql; 
    private final String startSql; 

    public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) { 
    super(be, ds, seqName, batchSize); 
    this.startSql = "values " 
    this.baseSql = "(nextval for " + seqName); 
    this.unionBaseSql = ", " + baseSql; 
    } 

    public String getSql(int batchSize) { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(startSql); 
    sb.append(baseSql); 
    for (int i = 1; i < batchSize; i++) { 
     sb.append(unionBaseSql); 
    } 

    return sb.toString(); 
    } 
} 
+0

你的設置是告訴JPA從序列獲取的ID值和插件內使用它。我猜這是干擾你的觸發器,也是設置ID值。打開JPA提供程序的日誌記錄並查看正在執行的語句以確定錯誤,但我認爲您應該不要在數據庫中使用觸發器。標識可能正在工作,因爲它告訴JPA提供程序查詢插入語句執行後設置的序列值,這與您的觸發器正在執行的操作相匹配。 – Chris

+0

'但是當使用ebean時,語句失敗......你不說錯誤是什麼?當然,Ebean並不期待觸發器在那裏。請注意,DB2支持Identity和Sequences ...因此推測是你已經考慮過了。 –

+0

不是Ebean是JPA的實現 - 它使用JPA註釋。如果不是,我會刪除提及。現在我已經包含了堆棧跟蹤,但其他日誌記錄沒有返回任何值得注意的事情。 我一直希望爲OracleDB和DB2使用相同的類,這就是爲什麼我試圖在DB2中實現序列生成ID –

回答

1

對於那些有興趣暫時的解決辦法:在ebean.properties,設置

ebean.databaseSequenceBatchSize=1