@Version 在修改集合时导致实体更新

问题描述 投票:0回答:1

我注意到,当我在实体上有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 将不会触发更新。它只是像预期的那样插入中间表。

spring hibernate jpa many-to-many entity
1个回答
0
投票

这是 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.

© www.soinside.com 2019 - 2024. All rights reserved.