我注意到,当我在实体上有ManyToMany关系和@Version字段时,当我尝试添加与该实体有关系的其他一些实体时,休眠会触发实体上的更新并更新版本。
这可能是我想要的,但如果我不想每次关系发生变化时都更新版本怎么办?使用@Version时有什么办法可以实现这一点吗?
我有一个小虚拟示例:
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class Shop {
@NotNull
@LastModifiedDate
@Column(name = "last_updated")
private Instant lastUpdated;
@NotNull
@Version
@Column(name="version")
private Long version;
@Id
@SequenceGenerator(name = "shop_id_seq", sequenceName = "shop_id_seq", allocationSize = 1)
@GeneratedValue(
generator = "shop_id_seq",
strategy = GenerationType.SEQUENCE
)
private Long id;
private String name;
@ManyToOne()
private Location location;
@OneToMany(mappedBy = "shop")
private List<ShopProduct> shopProducts;
@ManyToMany()
@JoinTable(
name="shop_worker",
joinColumns = @JoinColumn(name = "shop_id"),
inverseJoinColumns = @JoinColumn(name = "worker_id")
)
private Set<Worker> workers = new HashSet<>();
public void addWorker(Worker worker) {
workers.add(worker);
worker.getShops().add(this);
}
public void removeWorker(Worker worker) {
workers.remove(worker);
worker.getShops().remove(this);
}
}
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
public class Worker {
@NotNull
@LastModifiedDate
@Column(name = "last_updated")
private Instant lastUpdated;
@Id
@SequenceGenerator(name = "worker_id_seq", sequenceName = "worker_id_seq", allocationSize = 1)
@GeneratedValue(
generator = "worker_id_seq",
strategy = GenerationType.SEQUENCE
)
private Long id;
private String name;
@ManyToMany(mappedBy = "workers")
public Set<Shop> shops = new HashSet<>();
public void addShop(Shop shop) {
shops.add(shop);
shop.getWorkers().add(this);
}
public void removeShop(Shop shop) {
shops.remove(shop);
shop.getWorkers().remove(this);
}
}
@Test
@Transactional
void testAddingShopToWorker(){
System.out.println("TEST SETUP");
var shop = new Shop();
shop.setName("Shop1");
em.persist(shop);
em.flush();
em.clear();
System.out.println("TEST BEGINS");
Shop myShop = em.find(Shop.class, 1L);
var worker = new Worker();
worker.setName("John");
worker.addShop(myShop);
workerRepository.save(worker);
em.flush(); // hibernate triggers update on shop even though its not needed
}
来自日志: 休眠: 更新 店铺 放 最后更新=?, 位置 ID=?, 名字=?, 版本=? 在哪里 id=? 和版本=?
注意:当您注释掉版本字段时,hibernate 将不会触发更新。它只是像预期的那样插入中间表。
这是 JPA 规范 3.4.2 所要求的(我正在查看的 2.1):
“所有非关系字段和属性以及所有关系 实体拥有的内容包含在版本检查中[35]。”
和
“[35] 这包括在连接表中维护的拥有关系。”
如果你想避免这种情况,你需要使用原生 Hibernate API: https://stackoverflow.com/questions/33972564/is-it-possible-to-turn-off-hibernate-version-increment-for-pspecial-update#:~:text=Hibernate %20Optimistic%20Locking%20can%20be%20bypassed%20using%20hibernate,%2F%2FDetaching%20to%20prevent%20hibernate%20to%20spot%20dirty%20fields.