Issue
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 Product
s:
@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.
Solution
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.
Answered By - jwpol