correctly handle embeddable inheritance in HibernateProcessor

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-06-03 20:15:34 +02:00
parent 14631ddd8f
commit cdb92a3049
13 changed files with 192 additions and 22 deletions

View File

@ -361,18 +361,28 @@ public final class TypeUtils {
private static void updateEmbeddableAccessTypeForMember(Context context, AccessType defaultAccessType, Element member) {
final String embeddedClassName = member.asType().accept( new EmbeddedAttributeVisitor( context ), member );
if ( embeddedClassName != null ) {
final AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( embeddedClassName );
if ( accessTypeInfo == null ) {
final AccessTypeInformation newAccessTypeInfo =
new AccessTypeInformation( embeddedClassName, null, defaultAccessType );
context.addAccessTypeInformation( embeddedClassName, newAccessTypeInfo );
final TypeElement typeElement = context.getElementUtils().getTypeElement(embeddedClassName);
updateEmbeddableAccessType( typeElement, context, defaultAccessType );
}
else {
accessTypeInfo.setDefaultAccessType( defaultAccessType );
updateEmbeddableAccessType( context, defaultAccessType, embeddedClassName );
}
}
private static void updateEmbeddableAccessType(Context context, AccessType defaultAccessType, String embeddedClassName) {
final AccessTypeInformation accessTypeInfo = context.getAccessTypeInfo( embeddedClassName );
if ( accessTypeInfo == null ) {
final AccessTypeInformation newAccessTypeInfo =
new AccessTypeInformation( embeddedClassName, null, defaultAccessType );
context.addAccessTypeInformation( embeddedClassName, newAccessTypeInfo );
final TypeElement typeElement = context.getElementUtils().getTypeElement( embeddedClassName );
updateEmbeddableAccessType( typeElement, context, defaultAccessType );
final TypeMirror superclass = typeElement.getSuperclass();
if ( superclass.getKind() == TypeKind.DECLARED ) {
final DeclaredType declaredType = (DeclaredType) superclass;
final TypeElement element = (TypeElement) declaredType.asElement();
updateEmbeddableAccessType( context, defaultAccessType, element.getQualifiedName().toString() );
}
}
else {
accessTypeInfo.setDefaultAccessType(defaultAccessType);
}
}
private static @Nullable AccessType getDefaultAccessForHierarchy(TypeElement element, Context context) {

View File

@ -12,6 +12,7 @@ import java.util.TreeSet;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
/**
* @author Bogdan Știrbăț
@ -19,8 +20,14 @@ import jakarta.persistence.Entity;
@Entity
public class Homework {
private long id;
private List<String> paths;
@Id
public long getId() {
return id;
}
@ElementCollection
public List<String> getPaths() {
return paths;

View File

@ -10,12 +10,19 @@ import java.util.Map;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class OfficeBuilding {
private long id;
private Map<Integer, byte[]> doorCodes;
@Id
public long getId() {
return id;
}
@ElementCollection
public Map<Integer, byte[]> getDoorCodes() {
return doorCodes;

View File

@ -33,7 +33,7 @@ public class EmbeddableGenericsTest extends CompilationTest {
// "Expected Set for attribute named 'fields'"
// );
assertSuperClassRelationShipInMetamodel(
assertSuperclassRelationshipInMetamodel(
ChildEmbeddable.class,
ParentEmbeddable.class
);

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.processor.test.embeddable.genericsinheritance;
import org.hibernate.processor.test.util.CompilationTest;
import org.hibernate.processor.test.util.TestUtil;
import org.hibernate.processor.test.util.WithClasses;
import org.junit.Test;
import static org.hibernate.processor.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
import static org.hibernate.processor.test.util.TestUtil.assertMetamodelClassGeneratedFor;
import static org.hibernate.processor.test.util.TestUtil.assertSuperclassRelationshipInMetamodel;
public class EmbeddableGenericsAndInterfaceTest extends CompilationTest {
@Test @WithClasses({ExampleEntity.class, UserEntity.class, ExampleEmbedded.class, ExampleSuperClassEmbedded.class})
public void test() {
System.out.println( TestUtil.getMetaModelSourceAsString( ExampleEntity.class ) );
System.out.println( TestUtil.getMetaModelSourceAsString( ExampleSuperClassEmbedded.class ) );
System.out.println( TestUtil.getMetaModelSourceAsString( ExampleEmbedded.class ) );
System.out.println( TestUtil.getMetaModelSourceAsString( UserEntity.class ) );
assertMetamodelClassGeneratedFor( ExampleEntity.class );
assertMetamodelClassGeneratedFor( ExampleSuperClassEmbedded.class );
assertMetamodelClassGeneratedFor( ExampleEmbedded.class );
assertMetamodelClassGeneratedFor( UserEntity.class );
assertSuperclassRelationshipInMetamodel( ExampleEmbedded.class, ExampleSuperClassEmbedded.class );
assertAttributeTypeInMetaModelFor(
ExampleSuperClassEmbedded.class,
"user",
UserEntity.class,
"user should be inherited"
);
}
}

View File

@ -0,0 +1,13 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.processor.test.embeddable.genericsinheritance;
import jakarta.persistence.Embeddable;
@Embeddable
public class ExampleEmbedded<T> extends ExampleSuperClassEmbedded<T> {
}

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.processor.test.embeddable.genericsinheritance;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class ExampleEntity {
private int id;
private ExampleEmbedded<?> exampleEmbedded;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Embedded
public ExampleEmbedded<?> getExampleEmbedded() {
return exampleEmbedded;
}
public void setExampleEmbedded(ExampleEmbedded<?> exampleEmbedded) {
this.exampleEmbedded = exampleEmbedded;
}
}

View File

@ -0,0 +1,24 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.processor.test.embeddable.genericsinheritance;
import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MappedSuperclass;
@MappedSuperclass
public class ExampleSuperClassEmbedded<T> {
private UserEntity user;
@ManyToOne( fetch = FetchType.LAZY )
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
}

View File

@ -0,0 +1,35 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.processor.test.embeddable.genericsinheritance;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class UserEntity {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -12,7 +12,7 @@ import org.junit.Test;
import static org.hibernate.processor.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
import static org.hibernate.processor.test.util.TestUtil.assertPresenceOfFieldInMetamodelFor;
import static org.hibernate.processor.test.util.TestUtil.assertSuperClassRelationShipInMetamodel;
import static org.hibernate.processor.test.util.TestUtil.assertSuperclassRelationshipInMetamodel;
/**
* @author Emmanuel Bernard
@ -32,15 +32,15 @@ public class InheritanceTest extends CompilationTest {
public void testInheritance() throws Exception {
// entity inheritance
assertSuperClassRelationShipInMetamodel( Customer.class, User.class );
assertSuperclassRelationshipInMetamodel( Customer.class, User.class );
// mapped super class
assertSuperClassRelationShipInMetamodel( House.class, Building.class );
assertSuperClassRelationShipInMetamodel( Building.class, Area.class );
assertSuperclassRelationshipInMetamodel( House.class, Building.class );
assertSuperclassRelationshipInMetamodel( Building.class, Area.class );
// METAGEN-29
assertSuperClassRelationShipInMetamodel( Person.class, AbstractEntity.class );
assertSuperclassRelationshipInMetamodel( Person.class, AbstractEntity.class );
assertPresenceOfFieldInMetamodelFor( AbstractEntity.class, "id", "Property 'id' should exist" );
assertPresenceOfFieldInMetamodelFor( AbstractEntity.class, "foo", "Property should exist - METAGEN-29" );
assertAttributeTypeInMetaModelFor(

View File

@ -10,7 +10,7 @@ import org.hibernate.processor.test.util.CompilationTest;
import org.hibernate.processor.test.util.WithClasses;
import org.junit.Test;
import static org.hibernate.processor.test.util.TestUtil.assertSuperClassRelationShipInMetamodel;
import static org.hibernate.processor.test.util.TestUtil.assertSuperclassRelationshipInMetamodel;
/**
* @author Emmanuel Bernard
@ -27,7 +27,7 @@ public class UnmappedClassInHierarchyTest extends CompilationTest {
SubB.class
})
public void testUnmappedClassInHierarchy() throws Exception {
assertSuperClassRelationShipInMetamodel( SubA.class, BaseEntity.class );
assertSuperClassRelationShipInMetamodel( SubB.class, MappedBase.class );
assertSuperclassRelationshipInMetamodel( SubA.class, BaseEntity.class );
assertSuperclassRelationshipInMetamodel( SubB.class, MappedBase.class );
}
}

View File

@ -183,7 +183,7 @@ public class TestUtil {
assertEquals( buildErrorString( errorString, clazz ), expectedMapValue, actualMapKeyValue );
}
public static void assertSuperClassRelationShipInMetamodel(Class<?> entityClass, Class<?> superEntityClass) {
public static void assertSuperclassRelationshipInMetamodel(Class<?> entityClass, Class<?> superEntityClass) {
Class<?> clazz = getMetamodelClassFor( entityClass );
Class<?> superClazz = getMetamodelClassFor( superEntityClass );
assertEquals(

View File

@ -16,7 +16,7 @@ import org.junit.Test;
import static org.hibernate.processor.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
import static org.hibernate.processor.test.util.TestUtil.assertMetamodelClassGeneratedFor;
import static org.hibernate.processor.test.util.TestUtil.assertPresenceOfFieldInMetamodelFor;
import static org.hibernate.processor.test.util.TestUtil.assertSuperClassRelationShipInMetamodel;
import static org.hibernate.processor.test.util.TestUtil.assertSuperclassRelationshipInMetamodel;
/**
* @author Hardy Ferentschik
@ -86,7 +86,7 @@ public class XmlMappingTest extends CompilationTest {
public void testClassHierarchy() {
assertMetamodelClassGeneratedFor( Mammal.class );
assertMetamodelClassGeneratedFor( LivingBeing.class );
assertSuperClassRelationShipInMetamodel( Mammal.class, LivingBeing.class );
assertSuperclassRelationshipInMetamodel( Mammal.class, LivingBeing.class );
}
@Test(expected = ClassNotFoundException.class)