2016-05-10 115 views
0

我试图让hibernate处理并发性,经过一些研究后@Version的用法出来了。 下面遵循我在做什么,到目前为止的例子:@Version不能与@DynamicInsert一起工作

CREATE TABLE MY_TABLE (
    ID NUMBER NOT NULL 
    , VERSION NUMBER NOT NULL 
); 

ALTER TABLE MY_TABLE ADD CONSTRAINT PK_MY_TABLE KEY (ID); 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.SequenceGenerator; 
import javax.persistence.Table; 
import javax.persistence.Version; 

import org.hibernate.annotations.DynamicInsert; 
import org.hibernate.annotations.DynamicUpdate; 
import org.hibernate.annotations.Generated; 
import org.hibernate.annotations.GenerationTime; 

@Entity 
@Table(name = "MY_TABLE") 
@SequenceGenerator(name = "SQ_NAME", sequenceName = "SQ_MY_TABLE", initialValue = 1, allocationSize = 1) 
@DynamicUpdate 
@DynamicInsert 
public class MyTable implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @Column(name = "ID") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_NAME") 
    private Long id; 

    @Column(name = "VERSION", insertable = false, updatable = false) 
    @Version 
    @Generated(GenerationTime.ALWAYS) 
    private Long version; 

    ... getters and setters 
} 

当我的应用程序试图插入新行到MY_TABLE,甲骨文抛出异常

ORA-01400: cannot insert NULL into ("MY_TABLE"."VERSION") 

我缺少什么?它只适用于删除@DynamicInsert ...

PS:我正在使用@Generated(GenerationTime.ALWAYS),因为如果我不使用它,我不能在同一个记录上执行2次更新,而不必先调用它。环境:JBoss EAP 6.3,java 1.7.0_79,hibernate 4.3.11.Final(使用JTA),JSF 2.0和Oracle 12c。

回答

0

经过更多的研究,我发现当我们使用GenerationTime.ALWAYS或GenerationTime.INSERT时,我们需要提供一个数据库触发器来填充用@Version注释的字段。

在Oracle中,例如,触发是这样的:

CREATE OR REPLACE TRIGGER TRG_MY_TABLE_BIUR 
BEFORE INSERT OR UPDATE 
    ON MY_TABLE 
    FOR EACH ROW 
DECLARE 
BEGIN 
    IF INSERTING THEN 
     :NEW.VERSION := 0; 
    ELSE 
     :NEW.VERSION := :OLD.VERSION + 1; 
    END IF; 
END TRG_MY_TABLE_BIUR; 
/