[JIRA] (HHH-16821) Fail to delete entity that contains an embedded with a many to many association as field
by Andrea Boriero (JIRA)
Andrea Boriero ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMWYwNjVkMTBl... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16821?atlOrigin=eyJpIjoiMWYwNj... ) HHH-16821 ( https://hibernate.atlassian.net/browse/HHH-16821?atlOrigin=eyJpIjoiMWYwNj... ) Fail to delete entity that contains an embedded with a many to many association as field ( https://hibernate.atlassian.net/browse/HHH-16821?atlOrigin=eyJpIjoiMWYwNj... )
Change By: Andrea Boriero ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
h3 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 have contains an embedded which contain itself a compositeId with one of its id field part of describing a @ManyToOne many to many association.
h3. Entities
{code:java}@Getter
@ IdClass(ProductPK.class) Entity
@ EqualsAndHashCode ToString (onlyExplicitlyIncluded = true)
@ ToString EqualsAndHashCode (onlyExplicitlyIncluded = true)
@NoArgsConstructor(access = PROTECTED)
@ Entity Table(name = "TAG_OPERATORS")
@OptimisticLocking(type = OptimisticLockType.DIRTY)
@DynamicUpdate
@Cacheable
@ org.hibernate.annotations. Cache(usage = READ_WRITE)
@Table(name = "PRODUCTS")
public class Product TagOperator {
public Product TagOperator (String productId, Operator operator operatorId ) {
this. productId operatorId = productId operatorId ;
this. operator tagPolicy = operator new OperatorTagPolicy(Set.of(), ALL) ;
}
@EqualsAndHashCode.Include
@ToString.Include
@Id
@Column(name = " PRODUCT_ID OPERATOR_ID ", nullable = false)
private String productId operatorId ;
@Id
@ EqualsAndHashCode.Include Embedded
@ToString.Include private OperatorTagPolicy tagPolicy;
@ Getter Value
@ Setter AllArgsConstructor
@ Cache NoArgsConstructor ( usage access = READ_WRITE PROTECTED )
@ ManyToOne Embeddable
public static class OperatorTagPolicy {
@NonFinal
@ManyToMany (fetch = LAZY )
@JoinTable(
name = "OPERATOR_TO_TAG" , optional
joinColumns = false) {
@JoinColumn( nullable name = false "OPERATOR_ID", referencedColumnName = "OPERATOR_ID" )
private Operator operator; },
inverseJoinColumns = @ Column JoinColumn (name = " DESCRIPTION TAG_NAME ") )
@ Setter org.hibernate.annotations.Cache(usage = READ_WRITE)
private String description Set<Tag> exceptions ;
@ AllArgsConstructor NonFinal
@ EqualsAndHashCode Column(name = "TAG_POLICY_TYPE", nullable = false)
@ ToString
@NoArgsConstructor Enumerated ( access = PUBLIC EnumType.STRING )
public static class ProductPK implements Serializable {
private String productId PolicyType type ;
private String operator;
}
}
{code}
{code:java}
@ Getter
@ Entity
@ ToString Table ( onlyExplicitlyIncluded name = true "TAGS" )
@EqualsAndHashCode (onlyExplicitlyIncluded = true)
@NoArgsConstructor(access = PROTECTED)
@ Table(name = "OPERATORS") AllArgsConstructor
@ OptimisticLocking(type = OptimisticLockType.DIRTY) Getter
@DynamicUpdate
@Cacheable
@Cache(usage = READ_WRITE)
public class Operator Tag {
public Operator(String operatorId) {
this.operatorId = operatorId;
}
@ EqualsAndHashCode.Include
@ToString.Include
@ Id
@Column(name = " OPERATOR_ID TAG_NAME ", nullable = false)
private String operatorId name ;
@OneToMany(mappedBy = "operator", cascade = } { CascadeType.ALL code } , orphanRemoval = true, fetch = FetchType.LAZY)
private List<Product> products = new ArrayList<>();
{code:java} public void setProducts(List<Product> products) enum PolicyType {
this.products = products; ALL,
} NONE
}{code}
h3. Test
{code:java} @Test
void shouldDeleteProduct shouldDeleteTagOperator () {
// Given
String string = "ID2";
String operatorID = " operatorID2 tagOperatorID ";
String test = "test";
Operator TagOperator operator = new Operator TagOperator (operatorID);
operatorService tagOperatorService. addOperator addTagOperator (operator);
Product product = new Product(string, operator);
product tagOperatorService. setDescription deleteTagOperator ( test);
productService.addProduct(product);
// When
ProductPK productPK = new ProductPK(string, operatorID);
productService.deleteProduct(productPK);
// Then
Optional< Product TagOperator > byId2 = productService tagOperatorService. getProduct getTagOperator ( productPK operatorID );
assertThat(byId2).isEmpty();
}{code}
I get the following 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. ObjectOptimisticLockingFailureException jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java : Batch update returned unexpected row count from update [0]; actual row count 570)
...
Caused by : 0; expected jakarta.persistence.RollbackException : 1; statement executed: delete from products where operator_operator_id=? and product_id=? and operator_operator_id is null and product_id is null and description=? Error while committing the transaction
...
Caused by: java.lang.UnsupportedOperationException
at org. springframework hibernate. orm metamodel. jpa mapping. vendor internal. HibernateJpaDialect PluralAttributeMappingImpl. convertHibernateAccessException breakDownJdbcValues ( HibernateJpaDialect PluralAttributeMappingImpl.java: 307 975 )
at org. springframework hibernate. orm metamodel. jpa mapping. vendor internal. HibernateJpaDialect EmbeddableMappingTypeImpl. translateExceptionIfPossible breakDownJdbcValues ( HibernateJpaDialect EmbeddableMappingTypeImpl.java: 232 655 )
... {noformat}
h3. Be aware that the right attachment archive is the latest uploaded (I cannot delete attachment that were already uploaded).
GitHub repository with sources : [https://github.com/emouty/hibernate-issues|https://github.com/emouty/hibe...]
( https://hibernate.atlassian.net/browse/HHH-16821#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16821#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100228- sha1:e911e2c )
1 year, 5 months