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 {
}
}