Update generated after insert when bidirectional one to many mapping

huangapple go评论46阅读模式
英文:

Update generated after insert when bidirectional one to many mapping

问题

I am using bidirectional one to many relationship mapping for performance reason in order to have only inserts generated when persisting entities (according to one of the answers from What is the difference between Unidirectional and Bidirectional JPA and Hibernate associations?)

然而,当我在多侧未指定CascadeType.PERSIST时,我注意到插入后仍然生成了更新。

Hibernate: insert into promotion (deadline, description, percentage, promotion_id) values (?, ?, ?, ?)
Hibernate: update product set amount_in_stock=?, category_id=?, description=?, product_name=?, product_price=?, production_year=?, promotion_id=?, "size"=?, sold_amount=?, vendor=?, weight=? where product_id=?

Promotion 可以引用多个 Products:

@Entity
@Table(name = "product")
public class Product
{
    @Id
    @Column(name = "product_id")
    @SequenceGenerator(name = "product_id_sequence", sequenceName = "product_id_sequence", allocationSize = 1)
    @GeneratedValue(generator = "product_id_sequence", strategy = GenerationType.SEQUENCE)
    private Long productId;

    @ManyToOne(fetch = FetchType.LAZY) // cascade = CascadeType.PERSIST
    @JoinColumn(name = "promotion_id")
    private Promotion promotion;
   
    // setters, getters, other fields
}
@Entity
@Table(name = "Promotion")
public class Promotion
{
    @Id
    @Column(name = "PROMOTION_ID")
    @SequenceGenerator(name = "promotion_id_sequence", sequenceName = "promotion_id_sequence", allocationSize = 1)
    @GeneratedValue(generator = "promotion_id_sequence", strategy = GenerationType.SEQUENCE)
    private Long promotionId;

    @OneToMany(mappedBy = "promotion", cascade = CascadeType.ALL)
    private List<Product> products = new LinkedList<>();

    public void addProduct(Product product)
    {
        products.add(product);
        product.setPromotion(this);
    }
    // setters, getters, delete synchronization method, other fields
}

Persist logic (@DataJpaTest):

promotion.addProduct(product);
entityManager.persist(promotion);
entityManager.flush();

为什么会发生这种情况?

感谢阅读。

英文:

I am using bidirectional one to many relationship mapping for performance reason in order to have only inserts generated when persisting entities (according to one of the answers from What is the difference between Unidirectional and Bidirectional JPA and Hibernate associations?
)

However when I don't specify CascadeType.PERSIST on the many side I noticed that updates are still generated after inserts.

Hibernate: insert into promotion (deadline, description, percentage, promotion_id) values (?, ?, ?, ?)
Hibernate: update product set amount_in_stock=?, category_id=?, description=?, product_name=?, product_price=?, production_year=?, promotion_id=?, "size"=?, sold_amount=?, vendor=?, weight=? where product_id=?

Promotion can refer to many Products:

@Entity
@Table(name = "product")
public class Product
{
    @Id
    @Column(name = "product_id")
    @SequenceGenerator(name = "product_id_sequence", sequenceName = "product_id_sequence", allocationSize = 1)
    @GeneratedValue(generator = "product_id_sequence", strategy = GenerationType.SEQUENCE)
    private Long productId;

    @ManyToOne(fetch = FetchType.LAZY) // cascade = CascadeType.PERSIST
    @JoinColumn(name = "promotion_id")
    private Promotion promotion;
   
    // setters, getters, other fields
}
@Entity
@Table(name = "Promotion")
public class Promotion
{
    @Id
    @Column(name = "PROMOTION_ID")
    @SequenceGenerator(name = "promotion_id_sequence", sequenceName = "promotion_id_sequence", allocationSize = 1)
    @GeneratedValue(generator = "promotion_id_sequence", strategy = GenerationType.SEQUENCE)
    private Long promotionId;

    @OneToMany(mappedBy = "promotion", cascade = CascadeType.ALL)
    private List<Product> products = new LinkedList<>();

    public void addProduct(Product product)
    {
        products.add(product);
        product.setPromotion(this);
    }
    // setters, getters, delete synchronization method, other fields
}

Persist logic (@DataJpaTest):

promotion.addProduct(product);
entityManager.persist(promotion);
entityManager.flush();

Why it happens?

Thanks for reading.

答案1

得分: 0

以下是翻译好的部分:

这是发生的原因,因为在测试中,我持久化了与Product有关系的多个其他实体。然后,当Product处于托管状态时,通过调用entityManager.persist(promotion);,Hibernate必须通过添加promotion_id键来更新Product

entityManager.persist(category); // category有多个产品(添加了CascadeType.ALL)
entityManager.persist(promotion);
entityManager.flush();

我应该提供测试方法的更多代码行,但坦白说,我不知道它们会产生影响。总结一下,这不是映射的问题,而是持久化与彼此有关系的实体的顺序问题。最后,

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "promotion_id")
private Promotion promotion;

是正确的,不需要在Product一侧添加额外的级联。

英文:

It was happening, because in the test I was persisting several more entities which had relationship to Product. Then when Product was in manged state, by invoking entityManager.persist(promotion); hibernate had to update Product by adding promotion_id key.

entityManager.persist(category); // category has many products (CascadeType.ALL added)
entityManager.persist(promotion);
entityManager.flush();

I should have provided more lines of the test method, but frankly speaking I was not aware that they have some influence. So summing it up, it was not a problem of mapping, but an order of persisting the entities with relationships to one another. And finally

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "promotion_id")
private Promotion promotion;

is correct, that is no additional cascade required on the Product side.

huangapple
  • 本文由 发表于 2020年7月28日 03:28:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/63122231.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定