HHH-13620, HHH-13869 fix handling of nested embeddable access type in Processor

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-06-03 19:29:11 +02:00
parent ef1cbf589d
commit 9fbdafe318
10 changed files with 322 additions and 9 deletions

View File

@ -518,7 +518,7 @@ public class HibernateProcessor extends AbstractProcessor {
}
private static boolean isEntityOrEmbeddable(Element element) {
return containsAnnotation(
return hasAnnotation(
element,
ENTITY,
MAPPED_SUPERCLASS,
@ -550,7 +550,7 @@ public class HibernateProcessor extends AbstractProcessor {
private void handleRootElementAnnotationMirrors(final Element element) {
if ( isClassOrRecordType( element ) ) {
if ( hasAnnotation( element, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE ) ) {
if ( isEntityOrEmbeddable( element ) ) {
final TypeElement typeElement = (TypeElement) element;
indexEntityName( typeElement );
indexEnumFields( typeElement );

View File

@ -39,6 +39,7 @@ import java.util.Set;
import java.util.function.Function;
import static java.beans.Introspector.decapitalize;
import static org.hibernate.processor.util.AccessTypeInformation.DEFAULT_ACCESS_TYPE;
import static org.hibernate.processor.util.Constants.ACCESS;
import static org.hibernate.processor.util.Constants.BASIC;
import static org.hibernate.processor.util.Constants.ELEMENT_COLLECTION;
@ -70,9 +71,6 @@ public final class TypeUtils {
private static final Map<TypeKind, String> PRIMITIVE_WRAPPERS = new HashMap<>();
private static final Map<TypeKind, String> PRIMITIVES = new HashMap<>();
private static final String PROPERTY = AccessType.PROPERTY.toString();
private static final String FIELD = AccessType.FIELD.toString();
static {
PRIMITIVE_WRAPPERS.put( TypeKind.CHAR, "Character" );
@ -320,8 +318,7 @@ public final class TypeUtils {
// if we end up here we need to recursively look for superclasses
AccessType newDefaultAccessType = getDefaultAccessForHierarchy( searchedElement, context );
if ( newDefaultAccessType == null ) {
//TODO: this default is arbitrary and very questionable!
newDefaultAccessType = AccessType.PROPERTY;
newDefaultAccessType = DEFAULT_ACCESS_TYPE;
}
final AccessTypeInformation newAccessTypeInfo =
new AccessTypeInformation( qualifiedName, null, newDefaultAccessType );
@ -369,6 +366,8 @@ public final class TypeUtils {
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 );
@ -479,10 +478,10 @@ public final class TypeUtils {
if ( accessType != null ) {
final VariableElement enumValue = (VariableElement) accessType.getValue();
final Name enumValueName = enumValue.getSimpleName();
if ( enumValueName.contentEquals(PROPERTY) ) {
if ( enumValueName.contentEquals(AccessType.PROPERTY.name()) ) {
return AccessType.PROPERTY;
}
else if ( enumValueName.contentEquals(FIELD) ) {
else if ( enumValueName.contentEquals(AccessType.FIELD.name()) ) {
return AccessType.FIELD;
}
}

View File

@ -0,0 +1,49 @@
package org.hibernate.processor.test.embeddable.nested.field;
import jakarta.persistence.Embeddable;
import org.hibernate.processor.test.embeddable.nested.property.Postcode;
import java.util.Objects;
@Embeddable
public final class Address {
private String street;
private String city;
private org.hibernate.processor.test.embeddable.nested.property.Postcode postcode;
public String getStreet() {
return street;
}
public String getCity() {
return city;
}
public Postcode getPostcode() {
return postcode;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Address) obj;
return Objects.equals(this.street, that.street) &&
Objects.equals(this.city, that.city) &&
Objects.equals(this.postcode, that.postcode);
}
@Override
public int hashCode() {
return Objects.hash(street, city, postcode);
}
@Override
public String toString() {
return "Address[" +
"street=" + street + ", " +
"city=" + city + ", " +
"postcode=" + postcode + ']';
}
}

View File

@ -0,0 +1,19 @@
package org.hibernate.processor.test.embeddable.nested.field;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class Author {
@Id
String ssn;
@Basic(optional = false)
String name;
Address address;
Boolean deceased;
}

View File

@ -0,0 +1,32 @@
/*
* 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.nested.field;
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.assertAttributeTypeInMetaModelFor;
public class NestedEmbeddableTest extends CompilationTest {
@Test
@WithClasses({ Author.class, Address.class, Postcode.class })
public void testCorrectAccessTypeUsedForEmbeddable() {
assertAttributeTypeInMetaModelFor(
Address.class,
"city",
String.class,
"city should be String"
);
assertAttributeTypeInMetaModelFor(
Postcode.class,
"zip",
String.class,
"zip should be String"
);
}
}

View File

@ -0,0 +1,42 @@
package org.hibernate.processor.test.embeddable.nested.field;
import jakarta.persistence.Embeddable;
import java.util.Objects;
@Embeddable
public final class Postcode {
private String zip;
private String plusFour;
public String getZip() {
return zip;
}
public String getPlusFour() {
return plusFour;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Postcode) obj;
return Objects.equals(this.zip, that.zip) &&
Objects.equals(this.plusFour, that.plusFour);
}
@Override
public int hashCode() {
return Objects.hash(zip, plusFour);
}
@Override
public String toString() {
return "Postcode[" +
"zip=" + zip + ", " +
"plusFour=" + plusFour + ']';
}
}

View File

@ -0,0 +1,48 @@
package org.hibernate.processor.test.embeddable.nested.property;
import jakarta.persistence.Embeddable;
import java.util.Objects;
@Embeddable
public final class Address {
private String street;
private String city;
private Postcode postcode;
public String getStreet() {
return street;
}
public String getCity() {
return city;
}
public Postcode getPostcode() {
return postcode;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Address) obj;
return Objects.equals(this.street, that.street) &&
Objects.equals(this.city, that.city) &&
Objects.equals(this.postcode, that.postcode);
}
@Override
public int hashCode() {
return Objects.hash(street, city, postcode);
}
@Override
public String toString() {
return "Address[" +
"street=" + street + ", " +
"city=" + city + ", " +
"postcode=" + postcode + ']';
}
}

View File

@ -0,0 +1,51 @@
package org.hibernate.processor.test.embeddable.nested.property;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class Author {
String ssn;
String name;
Address address;
Boolean deceased;
@Id
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
@Basic(optional = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Boolean getDeceased() {
return deceased;
}
public void setDeceased(Boolean deceased) {
this.deceased = deceased;
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.nested.property;
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.assertAttributeTypeInMetaModelFor;
public class NestedEmbeddableTest extends CompilationTest {
@Test
@WithClasses({ Author.class, Address.class, Postcode.class })
public void testCorrectAccessTypeUsedForEmbeddable() {
assertAttributeTypeInMetaModelFor(
Address.class,
"city",
String.class,
"city should be String"
);
assertAttributeTypeInMetaModelFor(
Postcode.class,
"zip",
String.class,
"zip should be String"
);
}
}

View File

@ -0,0 +1,41 @@
package org.hibernate.processor.test.embeddable.nested.property;
import jakarta.persistence.Embeddable;
import java.util.Objects;
@Embeddable
public final class Postcode {
private String zip;
private String plusFour;
public String getZip() {
return zip;
}
public String getPlusFour() {
return plusFour;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Postcode) obj;
return Objects.equals(this.zip, that.zip) &&
Objects.equals(this.plusFour, that.plusFour);
}
@Override
public int hashCode() {
return Objects.hash(zip, plusFour);
}
@Override
public String toString() {
return "Postcode[" +
"zip=" + zip + ", " +
"plusFour=" + plusFour + ']';
}
}