As I understand from the MySQL documentation and from this question, it is NOT POSSIBLE to use deferred constraint in MySQL.
So, my question is; with below entity model (a uni-directional relation) in Hibernate, I want to swap two a collection of Package
between two Product
entities within a Transaction
.
public class Product{
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(
name="product_selected_packages",
joinColumns = {@JoinColumn(name = "product")},
inverseJoinColumns = {@JoinColumn(name="packages",unique = true)},
uniqueConstraints = {@UniqueConstraint(name = "UK_package",columnNames = {"packages"})}
)
private List<Package> packages;
}
public class Package {
@Column(unique = true)
private String code;
}
But when I write this type of code below (this is all done within a @Transactional
method),
List<Package> product1Packages = new ArrayList<>(product1.getPackages()); // save product1 packages into memory
product1.getPackages().clear(); // clear all product1 packages
session.flush(); // flush session in order to sync db with hibernate
product2.getPackages().addAll(product1Packages);
Of course there is a more complex logic behind it but in a general way, Hibernate produces below SQL(which makes sense)
START TRANSACTION;
DELETE FROM product_selected_packages WHERE product = :SOME_ID;
INSERT INTO product_selected_packages(product,packages) VALUES (1,1) , (1,2) , (1,3) ...;
ROLLBACK; -- OR COMMIT
But due to MySQL's limitations on constraints which is stated in the documentation; above statement throws an error.
Duplicate entry '1621' for key 'UK_unique_index_constraint'
Because documentation states;
MySQL checks foreign key constraints immediately; the check is not deferred to transaction commit.
Long story short, how can I create a work-around method for this type of situation without losing the Transaction
?