我试图让hibernate处理并发,经过一些研究后,@ Version的使用出来了。 下面是我到目前为止所做的一个例子:
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中插入新行时,Oracle会抛出异常
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 :(得分: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;
/