[JIRA] (HHH-16810) Fail to delete entity with a composite id using an @IdClass with one of its fields mapped from the id of a @ManyToOne association
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=eyJpIjoiZmYxNzgzYmE2... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16810?atlOrigin=eyJpIjoiZmYxNz... ) HHH-16810 ( https://hibernate.atlassian.net/browse/HHH-16810?atlOrigin=eyJpIjoiZmYxNz... ) Fail to delete entity with a composite id using an @IdClass with one of its fields mapped from the id of a @ManyToOne association ( https://hibernate.atlassian.net/browse/HHH-16810?atlOrigin=eyJpIjoiZmYxNz... )
Change By: Andrea Boriero ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
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 have a compositeId with one of its id field describing part of a many to many @ManyToOne association.
h3. Entities
{ code:java noformat }@Getter
@ Entity IdClass(ProductPK.class)
@ ToString EqualsAndHashCode (onlyExplicitlyIncluded = true)
@ EqualsAndHashCode ToString (onlyExplicitlyIncluded = true)
@NoArgsConstructor(access = PROTECTED)
@ Table(name = "TAG_OPERATORS") Entity
@OptimisticLocking(type = OptimisticLockType.DIRTY)
@DynamicUpdate
@Cacheable
@ org.hibernate.annotations. Cache(usage = READ_WRITE)
@Table(name = "PRODUCTS")
public class TagOperator Product {
public TagOperator Product (String operatorId productId, Operator operator ) {
this. operatorId productId = operatorId productId ;
this. tagPolicy operator = new OperatorTagPolicy(Set.of(), ALL) operator ;
}
@EqualsAndHashCode.Include
@ToString.Include
@Id
@Column(name = " OPERATOR_ID PRODUCT_ID ", nullable = false)
private String operatorId productId ;
@ Embedded Id
private OperatorTagPolicy tagPolicy;
@ Value EqualsAndHashCode.Include
@ AllArgsConstructor ToString.Include
@ NoArgsConstructor(access = PROTECTED) Getter
@ Embeddable Setter
public static class OperatorTagPolicy {
@ NonFinal
@ManyToMany Cache ( fetch usage = LAZY READ_WRITE )
@ JoinTable ManyToOne (
name fetch = "OPERATOR_TO_TAG" LAZY ,
joinColumns optional = { false)
@JoinColumn( name nullable = "OPERATOR_ID", referencedColumnName = "OPERATOR_ID" false )
}, private Operator operator;
inverseJoinColumns =
@ JoinColumn Column (name = " TAG_NAME DESCRIPTION ") )
@ org.hibernate.annotations.Cache(usage = READ_WRITE) Setter
Set<Tag> exceptions private String description ;
@ NonFinal AllArgsConstructor
@ Column(name = "TAG_POLICY_TYPE", nullable = false) EqualsAndHashCode
@ Enumerated ToString
@NoArgsConstructor ( EnumType.STRING access = PUBLIC )
PolicyType type public static class ProductPK implements Serializable {
private String productId ;
private String operator;
}
}
{ code noformat }
{ code:java noformat }@ Getter
@ Entity
@ Table ToString ( name onlyExplicitlyIncluded = "TAGS" true )
@EqualsAndHashCode (onlyExplicitlyIncluded = true)
@NoArgsConstructor(access = PROTECTED)
@ AllArgsConstructor Table(name = "OPERATORS")
@ Getter OptimisticLocking(type = OptimisticLockType.DIRTY)
@DynamicUpdate
@Cacheable
@Cache(usage = READ_WRITE)
public class Tag Operator {
public Operator(String operatorId) {
this.operatorId = operatorId;
}
@ EqualsAndHashCode.Include
@ToString.Include
@ Id
@Column(name = " TAG_NAME OPERATOR_ID ", nullable = false)
private String name operatorId ;
}{code}
@OneToMany(mappedBy = "operator", cascade = { code:java CascadeType.ALL } , orphanRemoval = true, fetch = FetchType.LAZY)
private List<Product> products = new ArrayList<>();
public enum PolicyType void setProducts(List<Product> products) {
ALL, this.products = products;
NONE }
}{ code noformat }
h3. Test
{ code:java noformat } @Test
void shouldDeleteTagOperator shouldDeleteProduct () {
// Given
String string = "ID2";
String operatorID = " tagOperatorID operatorID2 ";
TagOperator String test = "test";
Operator operator = new TagOperator Operator (operatorID);
tagOperatorService operatorService. addTagOperator addOperator (operator);
Product product = new Product(string, operator);
tagOperatorService product. deleteTagOperator setDescription ( test);
productService.addProduct(product);
// When
ProductPK productPK = new ProductPK(string, operatorID);
productService.deleteProduct(productPK);
// Then
Optional< TagOperator Product > byId2 = tagOperatorService productService. getTagOperator getProduct ( operatorID productPK );
assertThat(byId2).isEmpty();
}{ code noformat }
These tests raise an exception when I get the delete (or deleteAll) is committed.
{noformat}org.springframework.transaction.TransactionSystemException following exception : Could not commit JPA transaction
at
org.springframework.orm. jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java ObjectOptimisticLockingFailureException : 570)
...
Caused by Batch update returned unexpected row count from update [0]; actual row count : jakarta.persistence.RollbackException 0; expected : Error while committing the transaction
...
Caused by 1; statement executed : java.lang.UnsupportedOperationException delete from products where operator_operator_id=? and product_id=? and operator_operator_id is null and product_id is null and description=?
{noformat} at org. hibernate springframework. metamodel orm. mapping jpa. internal vendor. PluralAttributeMappingImpl HibernateJpaDialect. breakDownJdbcValues convertHibernateAccessException ( PluralAttributeMappingImpl HibernateJpaDialect.java: 975 307 )
at org. hibernate springframework. metamodel orm. mapping jpa. internal vendor. EmbeddableMappingTypeImpl HibernateJpaDialect. breakDownJdbcValues translateExceptionIfPossible ( EmbeddableMappingTypeImpl HibernateJpaDialect.java: 655 232 )
... {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-16810#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16810#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 )
2 years, 2 months