Error if defining a ManyToAny in the child classes which references a @MappedSuperclass

Hi,
When using a ManyToAny which references a @MappedSuperclass (not @Entity) and configuring it in the different child classes via the @Access(PROPERTY) getter, I have a NullPointerException in the comparison of lists that have the same name.

keyMapping and metaMapping are null.
And there is also a small comparison error between meta and key.

I made a test class to reproduce the issue. Note that the class referenced by the set must be a @MappedSuperclass for the error to occur (using an Any instead of a ManyToOne in the collection element).

package org.hibernate.orm.test.associations.any;

import static jakarta.persistence.InheritanceType.SINGLE_TABLE;
import static org.hibernate.annotations.CascadeType.ALL;

import java.util.HashSet;
import java.util.Set;

import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;

import org.hibernate.annotations.AnyKeyJavaClass;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.ManyToAny;

import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;

@Jpa(
		annotatedClasses = {
				ManyToAnySubClassAccessPropertyTest.Person.class,
				ManyToAnySubClassAccessPropertyTest.Animal.class,
				ManyToAnySubClassAccessPropertyTest.Cat.class,
				ManyToAnySubClassAccessPropertyTest.Dog.class,
				ManyToAnySubClassAccessPropertyTest.DogHandler.class,
				ManyToAnySubClassAccessPropertyTest.Military.class,
		}
)
@JiraKey("HHH-77777")
class ManyToAnySubClassAccessPropertyTest {

	@Test
	void testManyToAnyThatReferencedAMappedSuperclassDefinedInMultipleSubClass(EntityManagerFactoryScope scope) {
		scope.inTransaction(
				entityManager -> {
					Dog dog = new Dog();
					dog.getOwners().add( new DogHandler() );
					entityManager.persist( dog );
				}
		);
	}

	@Entity
	@Inheritance(strategy = SINGLE_TABLE)
	@DiscriminatorColumn(name = "ROLE", length = 100)
	@Table(name = "TANIMAL")
	public static class Animal {

		@Id
		@GeneratedValue
		public Integer id;

		@Transient
		private Set<Person> owners = new HashSet<>();

		public Set<Person> getOwners() {
			return owners;
		}

		public void setOwners(Set<Person> owners) {
			this.owners = owners;
		}
	}

	@Entity
	@DiscriminatorValue("DOG")
	public static class Dog extends Animal {

		@Access(AccessType.PROPERTY)
		@ManyToAny
		@AnyKeyJavaClass(Integer.class)
		@Cascade(ALL)
		@Column(name = "ROLE")
		@JoinTable(name = "DOG_OWNER", joinColumns = @JoinColumn(name = "SOURCE"), inverseJoinColumns = @JoinColumn(name = "DEST"))
		@Override
		public Set<Person> getOwners() {
			return super.getOwners();
		}
	}

	@Entity
	@DiscriminatorValue("CAT")
	public static class Cat extends Animal {

		@Access(AccessType.PROPERTY)
		@ManyToAny
		@AnyKeyJavaClass(Integer.class)
		@Cascade(ALL)
		@Column(name = "ROLE")
		@JoinTable(name = "DOG_OWNER", joinColumns = @JoinColumn(name = "SOURCE"), inverseJoinColumns = @JoinColumn(name = "DEST"))
		@Override
		public Set<Person> getOwners() {
			return super.getOwners();
		}
	}

	@MappedSuperclass
	public static class Person {

		@Id
		@GeneratedValue
		private Integer id;
	}

	@Entity
	public static class DogHandler extends Person {
	}

	@Entity
	public static class Military extends Person {
	}
}


Hi. Please create a Jira issue and attach that reproducer :slight_smile:

1 Like

https://hibernate.atlassian.net/browse/HHH-17871

HHH-17871 Error if defining a ManyToAny in the child classes which references a @MappedSuperclass by boutss · Pull Request #8012 · hibernate/hibernate-orm (github.com)

I have an error in the PR with sybase ?

I don’t see the link between JIRA and the pull request. Does this always work?

Hey @boutss, thanks for taking the time to open a PR. Looks like Sybase doesn’t like ROLE as a column name:

ManyToAnySubClassAccessPropertyTest > testManyToAnyThatReferencedAMappedSuperclassDefinedInMultipleSubClass(EntityManagerFactoryScope) FAILED
    jakarta.persistence.RollbackException: Error while committing the transaction
        at app//org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:67)
        at app//org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
        at app//org.hibernate.testing.orm.transaction.TransactionUtil.wrapInTransaction(TransactionUtil.java:54)
        at app//org.hibernate.testing.orm.transaction.TransactionUtil.inTransaction(TransactionUtil.java:28)
        at app//org.hibernate.testing.orm.junit.AbstractEntityManagerFactoryScope.inTransaction(AbstractEntityManagerFactoryScope.java:151)
        at app//org.hibernate.testing.orm.junit.AbstractEntityManagerFactoryScope.inTransaction(AbstractEntityManagerFactoryScope.java:127)
        at app//org.hibernate.orm.test.associations.any.ManyToAnySubClassAccessPropertyTest.testManyToAnyThatReferencedAMappedSuperclassDefinedInMultipleSubClass(ManyToAnySubClassAccessPropertyTest.java:51)

        Caused by:
        org.hibernate.exception.GenericJDBCException: could not execute statement [Incorrect syntax near the keyword 'ROLE'.
        ] [insert into TANIMAL (ROLE,id) values ('DOG',?)]

You can just rename it to something like role_col.

1 Like

I tested the fix in my project and didn’t encounter any problems afterwards.
Do you think the PR could be accepted for the next version?