添加子关系时如何使 Hibernate 不增加父实体的版本列(@ManyToMany 集合)
How to make Hibernate not increment Version column of parent entity when adding a child relationship (@ManyToMany collection)
表格:
create table myuser.A (
id number primary key,
notes varchar2(50),
version number);
create table myuser.B (
id number primary key,
username varchar2(50),
version number);
create table myuser.A_B (
a_id number,
b_id number,
constraint a_fk foreign key (a_id) references A(id),
constraint b_fk foreign key (b_id) references B(id)
);
insert into myuser.A values ('1', 'notes', 1);
insert into myuser.B values ('44', 'username', 1);
insert into myuser.A_B values ('1', '44');
注释 Hibernate 映射:
@Entity
class A {
@Id
@Column
public String id;
@Column
public String notes;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "A_B",
joinColumns = { @JoinColumn(name = "A_ID") },
inverseJoinColumns = { @JoinColumn(name = "B_ID") })
public Set<B> bDomains;
@Version
public int version;
}
@Entity
class B {
@Id
@Column
public String id;
@Column
public String username;
@ManyToMany(fetch = FetchType.EAGER, mappedBy = "bDomains")
public Set<A> aDomains;
@Version
public int version;
}
获取现有 'A' 对象并将新的子对象添加到 ManyToMany 集合。所以 'A' 对象没有改变,但是 Hibernate 为它生成一个新的版本号并更新 'A' table:
A a = session.get(A.class, "1");
int versionBefore = a.version;
B b = new B();
b.id = "48";
b.username = "asd";
a.bDomains.add(b);
session.save(a);
session.flush();
int versionAfter = a.version;
System.out.println("version before: " + versionBefore);
System.out.println("version after: " + versionAfter);
输出:
Hibernate: select a0_.id as id1_0_0_, a0_.notes as notes2_0_0_, a0_.version as version3_0_0_, bdomains1_.A_ID as A_ID1_1_1_, b2_.id as B_ID2_1_1_, b2_.id as id1_2_2_, b2_.username as username2_2_2_, b2_.version as version3_2_2_ from A a0_, A_B bdomains1_, B b2_ where a0_.id=bdomains1_.A_ID(+) and bdomains1_.B_ID=b2_.id(+) and a0_.id=?
Hibernate: select adomains0_.B_ID as B_ID2_1_0_, adomains0_.A_ID as A_ID1_1_0_, a1_.id as id1_0_1_, a1_.notes as notes2_0_1_, a1_.version as version3_0_1_ from A_B adomains0_, A a1_ where adomains0_.A_ID=a1_.id and adomains0_.B_ID=?
Hibernate: select b_.id, b_.username as username2_2_, b_.version as version3_2_ from B b_ where b_.id=?
Hibernate: insert into B (username, version, id) values (?, ?, ?)
Hibernate: update A set notes=?, version=? where id=? and version=?
Hibernate: insert into A_B (A_ID, B_ID) values (?, ?)
version before: 1
version after: 2
我不需要对休眠生成的 A table 进行更新查询,因为 A table 在这个逻辑中没有改变。
据我所知,Hibernate 会在更改实体的任何字段时增加版本列,即使该字段只是对另一个 table 的引用。我如何配置 Hibernate 以防止实体的版本增加,如果只是它的关系发生变化?
我找到了解决办法。
需要在 @ManyToMany|@OneToMany
属性.
上添加 @org.hibernate.annotations.OptimisticLock(excluded = true)
注释
因此,我示例中的 A
实体现在看起来像这样:
@Entity
class A {
@Id
@Column
public String id;
@Column
public String notes;
@org.hibernate.annotations.OptimisticLock(excluded = true)
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "A_B",
joinColumns = { @JoinColumn(name = "A_ID") },
inverseJoinColumns = { @JoinColumn(name = "B_ID") })
public Set<B> bDomains;
@Version
public int version;
}
生成的 SQL:
Hibernate: select a0_.id as id1_0_0_, a0_.notes as notes2_0_0_, a0_.version as version3_0_0_, bdomains1_.A_ID as A_ID1_1_1_, b2_.id as B_ID2_1_1_, b2_.id as id1_2_2_, b2_.username as username2_2_2_, b2_.version as version3_2_2_ from A a0_, A_B bdomains1_, B b2_ where a0_.id=bdomains1_.A_ID(+) and bdomains1_.B_ID=b2_.id(+) and a0_.id=?
Hibernate: select adomains0_.B_ID as B_ID2_1_0_, adomains0_.A_ID as A_ID1_1_0_, a1_.id as id1_0_1_, a1_.notes as notes2_0_1_, a1_.version as version3_0_1_ from A_B adomains0_, A a1_ where adomains0_.A_ID=a1_.id and adomains0_.B_ID=?
Hibernate: select b_.id, b_.username as username2_2_, b_.version as version3_2_ from B b_ where b_.id=?
Hibernate: insert into B (username, version, id) values (?, ?, ?)
Hibernate: insert into A_B (A_ID, B_ID) values (?, ?)
version before: 1
version after: 1
唯一的问题是 OptimisticLock 注释来自 Hibernate,而不是 JPA。
表格:
create table myuser.A (
id number primary key,
notes varchar2(50),
version number);
create table myuser.B (
id number primary key,
username varchar2(50),
version number);
create table myuser.A_B (
a_id number,
b_id number,
constraint a_fk foreign key (a_id) references A(id),
constraint b_fk foreign key (b_id) references B(id)
);
insert into myuser.A values ('1', 'notes', 1);
insert into myuser.B values ('44', 'username', 1);
insert into myuser.A_B values ('1', '44');
注释 Hibernate 映射:
@Entity
class A {
@Id
@Column
public String id;
@Column
public String notes;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "A_B",
joinColumns = { @JoinColumn(name = "A_ID") },
inverseJoinColumns = { @JoinColumn(name = "B_ID") })
public Set<B> bDomains;
@Version
public int version;
}
@Entity
class B {
@Id
@Column
public String id;
@Column
public String username;
@ManyToMany(fetch = FetchType.EAGER, mappedBy = "bDomains")
public Set<A> aDomains;
@Version
public int version;
}
获取现有 'A' 对象并将新的子对象添加到 ManyToMany 集合。所以 'A' 对象没有改变,但是 Hibernate 为它生成一个新的版本号并更新 'A' table:
A a = session.get(A.class, "1");
int versionBefore = a.version;
B b = new B();
b.id = "48";
b.username = "asd";
a.bDomains.add(b);
session.save(a);
session.flush();
int versionAfter = a.version;
System.out.println("version before: " + versionBefore);
System.out.println("version after: " + versionAfter);
输出:
Hibernate: select a0_.id as id1_0_0_, a0_.notes as notes2_0_0_, a0_.version as version3_0_0_, bdomains1_.A_ID as A_ID1_1_1_, b2_.id as B_ID2_1_1_, b2_.id as id1_2_2_, b2_.username as username2_2_2_, b2_.version as version3_2_2_ from A a0_, A_B bdomains1_, B b2_ where a0_.id=bdomains1_.A_ID(+) and bdomains1_.B_ID=b2_.id(+) and a0_.id=?
Hibernate: select adomains0_.B_ID as B_ID2_1_0_, adomains0_.A_ID as A_ID1_1_0_, a1_.id as id1_0_1_, a1_.notes as notes2_0_1_, a1_.version as version3_0_1_ from A_B adomains0_, A a1_ where adomains0_.A_ID=a1_.id and adomains0_.B_ID=?
Hibernate: select b_.id, b_.username as username2_2_, b_.version as version3_2_ from B b_ where b_.id=?
Hibernate: insert into B (username, version, id) values (?, ?, ?)
Hibernate: update A set notes=?, version=? where id=? and version=?
Hibernate: insert into A_B (A_ID, B_ID) values (?, ?)
version before: 1
version after: 2
我不需要对休眠生成的 A table 进行更新查询,因为 A table 在这个逻辑中没有改变。 据我所知,Hibernate 会在更改实体的任何字段时增加版本列,即使该字段只是对另一个 table 的引用。我如何配置 Hibernate 以防止实体的版本增加,如果只是它的关系发生变化?
我找到了解决办法。
需要在 @ManyToMany|@OneToMany
属性.
@org.hibernate.annotations.OptimisticLock(excluded = true)
注释
因此,我示例中的 A
实体现在看起来像这样:
@Entity
class A {
@Id
@Column
public String id;
@Column
public String notes;
@org.hibernate.annotations.OptimisticLock(excluded = true)
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "A_B",
joinColumns = { @JoinColumn(name = "A_ID") },
inverseJoinColumns = { @JoinColumn(name = "B_ID") })
public Set<B> bDomains;
@Version
public int version;
}
生成的 SQL:
Hibernate: select a0_.id as id1_0_0_, a0_.notes as notes2_0_0_, a0_.version as version3_0_0_, bdomains1_.A_ID as A_ID1_1_1_, b2_.id as B_ID2_1_1_, b2_.id as id1_2_2_, b2_.username as username2_2_2_, b2_.version as version3_2_2_ from A a0_, A_B bdomains1_, B b2_ where a0_.id=bdomains1_.A_ID(+) and bdomains1_.B_ID=b2_.id(+) and a0_.id=?
Hibernate: select adomains0_.B_ID as B_ID2_1_0_, adomains0_.A_ID as A_ID1_1_0_, a1_.id as id1_0_1_, a1_.notes as notes2_0_1_, a1_.version as version3_0_1_ from A_B adomains0_, A a1_ where adomains0_.A_ID=a1_.id and adomains0_.B_ID=?
Hibernate: select b_.id, b_.username as username2_2_, b_.version as version3_2_ from B b_ where b_.id=?
Hibernate: insert into B (username, version, id) values (?, ?, ?)
Hibernate: insert into A_B (A_ID, B_ID) values (?, ?)
version before: 1
version after: 1
唯一的问题是 OptimisticLock 注释来自 Hibernate,而不是 JPA。