2

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.

jwpol
  • 1,188
  • 10
  • 22

1 Answers1

0

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.

jwpol
  • 1,188
  • 10
  • 22