[JIRA] (HHH-15591) Unidirectional @OneToMany with @OrderColumn still throwing ConstraintViolationException (unique index violation)
by Burkhard Graves (JIRA)
Burkhard Graves ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNjdmZTI3NDQx... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-15591?atlOrigin=eyJpIjoiNjdmZT... ) HHH-15591 ( https://hibernate.atlassian.net/browse/HHH-15591?atlOrigin=eyJpIjoiNjdmZT... ) Unidirectional @OneToMany with @OrderColumn still throwing ConstraintViolationException (unique index violation) ( https://hibernate.atlassian.net/browse/HHH-15591?atlOrigin=eyJpIjoiNjdmZT... )
Change By: Burkhard Graves ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
There are several tickets dealing with this setup, see linked issues.
What seems to work by now :
* Adding one or more elements to the list
* Removing one or more elements from the list
What still does not work:
* Swapping elements in the list
* Simultaneously adding and removing elements from the list
I created a PR which adds two tests to {{UnidirectionalOneToManyOrderColumnTest}}, namely
{code:java} @Test
public void testSwapElementsAtZeroAndOne(EntityManagerFactoryScope scope) {
long parentId = scope.fromTransaction(
entityManager -> {
ParentData parent = new ParentData();
entityManager.persist( parent );
String[] childrenStr = new String[] {"One", "Two"};
for ( String str : childrenStr ) {
ChildData child = new ChildData( str );
entityManager.persist( child );
parent.getChildren().add( child );
}
entityManager.flush();
List<ChildData> children = parent.getChildren();
ChildData child0 = children.get( 0 );
ChildData child1 = children.get( 1 );
children.set(0, child1);
children.set(1, child0);
return parent.id;
}
);
// if the above works, then test on {"Two", "One"}
}
@Test
public void testAddAtZeroDeleteAtTwo(EntityManagerFactoryScope scope) {
long parentId = scope.fromTransaction(
entityManager -> {
ParentData parent = new ParentData();
entityManager.persist( parent );
String[] childrenStr = new String[] {"One", "Two"};
for ( String str : childrenStr ) {
ChildData child = new ChildData( str );
entityManager.persist( child );
parent.getChildren().add( child );
}
entityManager.flush();
List<ChildData> children = parent.getChildren();
children.add( 0, new ChildData( "Zero" ) );
children.remove( 2 );
return parent.id;
}
);
// if the above works, then test on {"Zero", "One"}
}{code}
Both tests fail (in h2 and presumably many other databases).
( https://hibernate.atlassian.net/browse/HHH-15591#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-15591#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#100208- sha1:492d0ce )
2 years, 2 months
[JIRA] (HHH-15602) ByteBuddy enhancement generates faulty code with many-to-many associations
by Thomas Mogwitz (JIRA)
Thomas Mogwitz ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=6319ba4... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiMGMyYjg0ZDBk... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-15602?atlOrigin=eyJpIjoiMGMyYj... ) HHH-15602 ( https://hibernate.atlassian.net/browse/HHH-15602?atlOrigin=eyJpIjoiMGMyYj... ) ByteBuddy enhancement generates faulty code with many-to-many associations ( https://hibernate.atlassian.net/browse/HHH-15602?atlOrigin=eyJpIjoiMGMyYj... )
Issue Type: Bug Affects Versions: 5.3.27, 6.1.4 Assignee: Unassigned Components: bytecode-enhancement Created: 13/Oct/2022 07:30 AM Priority: Minor Reporter: Thomas Mogwitz ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=6319ba4... )
SpotBugs reports a high-prio warning in entity classes that have been enhanced with ByteBuddy enhancement:
EC: Using pointer equality to compare different types (EC_UNRELATED_TYPES_USING_POINTER_EQUALITY)
-------------------------------------------------------------------------------------------------
This method uses pointer equality to compare two references that seem to be of different types. The result of this comparison will always be false at runtime.
The faulty code is in the generated many-to-many handler functions. Here's the relevant part of org.hibernate.bytecode.enhance.internal.bytebuddy.CodeTemplates
static class ManyToManyHandler {
(a)Advice.OnMethodEnter
static void enter((a)Advice.This Object self, @FieldValue Collection<?> field, @Advice.Argument(0) Collection<?> argument, @MappedBy String mappedBy) {
if ( field != null && Hibernate.isPropertyInitialized( field, mappedBy ) ) {
Object[] array = field.toArray();
for ( Object array1 : array ) {
if ( argument == null || !argument.contains( array1 ) ) {
getter( array1 ).remove( self );
}
}
}
}
(a)Advice.OnMethodExit
static void exit((a)Advice.This Object self, @Advice.Argument(0) Collection<?> argument, @MappedBy String mappedBy) {
if ( argument != null && Hibernate.isPropertyInitialized( argument, mappedBy ) ) {
Object[] array = argument.toArray();
for ( Object array1 : array ) {
if ( Hibernate.isPropertyInitialized( array1, mappedBy ) ) {
Collection<Object> c = getter( array1 );
if ( c != self && c != null ) { // <- pointer-comparing a collection and an entity object
c.add( self );
}
}
}
}
}
static Collection<Object> getter(Object self) {
// is replaced by the actual method call
throw new AssertionError();
}
}
I believe that the intended conditions in the if-statement in line 21 should have been:
if (c != null && !c.contains(self) )
The bug has been around at least since 5.3.27, probably even eralier, and is still there in the current version.
( https://hibernate.atlassian.net/browse/HHH-15602#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-15602#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#100208- sha1:492d0ce )
2 years, 2 months