h5. Description
I'm migrating from hibernate 5.6.15 to hibernate 6.2.5 and I have noticed some issues when I try to delete an entity that contains an embedded which contain itself a field describing a many to many association.
h3. Entities
{code:java}@Getter @Entity @ToString(onlyExplicitlyIncluded = true) @EqualsAndHashCode(onlyExplicitlyIncluded = true) @NoArgsConstructor(access = PROTECTED) @Table(name = "OPERATORS") @OptimisticLocking(type = OptimisticLockType.DIRTY) @DynamicUpdate @Cacheable @Cache(usage = READ_WRITE) public class Operator {
public Operator(String operatorId) { this.operatorId = operatorId; this.tagPolicy = new OperatorTagPolicy(Set.of(), ALL); }
@EqualsAndHashCode.Include @ToString.Include @Id @Column(name = "OPERATOR_ID", nullable = false) private String operatorId;
@Embedded private OperatorTagPolicy tagPolicy;
@OneToMany(mappedBy = "operator", cascade = {CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.LAZY) private List<Product> products = new ArrayList<>();
public void setProducts(List<Product> products) { this.products = products; }
@Value @AllArgsConstructor @NoArgsConstructor(access = PROTECTED) @Embeddable public static class OperatorTagPolicy { @NonFinal @ManyToMany(fetch = LAZY) @JoinTable( name = "OPERATOR_TO_TAG", joinColumns = { @JoinColumn(name = "OPERATOR_ID", referencedColumnName = "OPERATOR_ID") }, inverseJoinColumns = @JoinColumn(name = "TAG_NAME")) @Cache(usage = READ_WRITE) Set<Tag> exceptions;
@NonFinal @Column(name = "TAG_POLICY_TYPE", nullable = false) @Enumerated(EnumType.STRING) PolicyType type; } }{code}
{code:java}@Entity @Table(name = "TAGS") @EqualsAndHashCode @NoArgsConstructor(access = PROTECTED) @AllArgsConstructor @Getter public class Tag { @Id @Column(name = "TAG_NAME", nullable = false) private String name; }{code}
{code:java}public enum PolicyType { ALL, NONE }{code}
h3. Tests
{ noformat code:java } @Test @Order(2) void shouldDeleteOperator() { String string = "ID2"; String operatorID = "operatorID2"; String test = "test"; Operator operator = new Operator(operatorID); operatorDao.save(operator); Product product = new Product(string, operator); product.setDescription(test); productService.addProduct(product);
operatorService.deleteOperator(operatorID);
Optional<Operator> byId2 = operatorService.getOperator(operatorID); assertThat(byId2).isEmpty(); }
@Test @Order(3) void shouldDeleteAllOperators() { String string = "ID3"; String operatorID = "operatorID3"; String test = "test"; Operator operator = new Operator(operatorID); operatorDao.save(operator); Product product = new Product(string, operator); product.setDescription(test); productService.addProduct(product);
operatorService.deleteAllOperators();
Optional<Operator> byId2 = operatorService.getOperator(operatorID); assertThat(byId2).isEmpty(); }{ noformat code }
These tests raise an exception when the delete (or deleteAll) is committed.
{noformat}org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:570) ... Caused by: jakarta.persistence.RollbackException: Error while committing the transaction ... Caused by: java.lang.UnsupportedOperationException at org.hibernate.metamodel.mapping.internal.PluralAttributeMappingImpl.breakDownJdbcValues(PluralAttributeMappingImpl.java:975) at org.hibernate.metamodel.mapping.internal.EmbeddableMappingTypeImpl.breakDownJdbcValues(EmbeddableMappingTypeImpl.java:655) ...{noformat}
GitHub repository with sources : [https://github.com/emouty/hibernate-L2-cache-issue|https://github.com/emouty/hibernate-L2-cache-issue|smart-link] |
|