Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -481,10 +481,22 @@ private boolean mapAsIdClass(
final ClassDetails classWithIdClass = inheritanceState.getClassWithIdClass( false );
if ( classWithIdClass != null ) {
final IdClass idClassAnn = classWithIdClass.getDirectAnnotationUsage( IdClass.class );
final Class<?> idClassValue = idClassAnn.value();
final ClassDetails compositeClass =
getMetadataCollector().getSourceModelBuildingContext().getClassDetailsRegistry()
.resolveClassDetails( idClassValue.getName() );
final ClassDetails compositeClass;
if ( idClassAnn == null ) {
try {
compositeClass = getMetadataCollector().getSourceModelBuildingContext()
.getClassDetailsRegistry()
.resolveClassDetails( inheritanceState.getClassDetails().getClassName() + "_$Id" );
}
catch (RuntimeException e) {
return false;
}
}
else {
final Class<?> idClassValue = idClassAnn.value();
compositeClass = getMetadataCollector().getSourceModelBuildingContext()
.getClassDetailsRegistry().resolveClassDetails( idClassValue.getName() );
}
final TypeDetails compositeType = new ClassTypeDetailsImpl( compositeClass, TypeDetails.Kind.CLASS );
final TypeDetails classWithIdType = new ClassTypeDetailsImpl( classWithIdClass, TypeDetails.Kind.CLASS );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import org.hibernate.AnnotationException;
import org.hibernate.boot.spi.AccessType;
Expand Down Expand Up @@ -183,6 +184,13 @@ else if ( classDetails.hasDirectAnnotationUsage( IdClass.class ) ) {
return classDetails;
}
else {
final long count = Stream.concat(
classDetails.getFields().stream(),
classDetails.getMethods().stream()
).filter( t -> t.hasDirectAnnotationUsage( Id.class ) ).count();
if ( count > 1 ) {
return classDetails;
}
final InheritanceState state = getSuperclassInheritanceState( classDetails, inheritanceStatePerClass );
if ( state != null ) {
return state.getClassWithIdClass( true );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import org.hibernate.annotations.processing.Exclude;

@SuppressWarnings("serial")
@Entity
@Exclude
@Table(name = "orders")
public class Order implements Serializable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import org.hibernate.annotations.processing.Exclude;

@SuppressWarnings("serial")
@Entity
@Exclude
@Table(name = "order_line")
// @IdClass(OrderLinePK.class)
public class OrderLine implements Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.processing.Exclude;

@SuppressWarnings("serial")
@Entity
@Exclude
@Table(name = "products")
public class Product implements Serializable
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.mapping.hhh18829;

import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationTargetException;

import static org.junit.jupiter.api.Assertions.assertEquals;

@DomainModel(annotatedClasses = EmployeeWithoutIdClass.class)
@JiraKey(" HHH-18829")
@SessionFactory
public class AutoGeneratedIdClassTest {

@BeforeAll
void setUp(SessionFactoryScope sessionFactoryScope) {
sessionFactoryScope.inTransaction( sess -> {
final var one = new EmployeeWithoutIdClass();
one.empName = "John Doe";
one.empId = 1;
one.address = "10 Downing Street, SW1A 2AA";
sess.persist( one );

final var two = new EmployeeWithoutIdClass();
two.empName = "Dave Default";
two.empId = 1;
two.address = "1600 Pennsylvania Avenue";
sess.persist( two );
} );
}

@Test
public void test(SessionFactoryScope sessionFactoryScope)
throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {
final var idClass = Class.forName( EmployeeWithoutIdClass.class.getName() + "_$Id" );
final var id = idClass.getConstructors()[0].newInstance( "John Doe", 1 );
final var employees = sessionFactoryScope.fromSession(
sess -> sess.createQuery( "from EmployeeWithoutIdClass where id=:id", EmployeeWithoutIdClass.class ).setParameter( "id", id )
.getResultList()
);
assertEquals( 1, employees.size() );
assertEquals( "10 Downing Street, SW1A 2AA", employees.get( 0 ).address );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.mapping.hhh18829;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class EmployeeWithoutIdClass {
@Id
String empName;
@Id
Integer empId;
String address;
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@
*/
public class AnnotationMetaEntity extends AnnotationMeta {

private static final String ID_CLASS_MEMBER_NAME = "<ID_CLASS>";

private final ImportContext importContext;
private final TypeElement element;
private final Map<String, MetaAttribute> members;
Expand Down Expand Up @@ -443,6 +445,8 @@ && containsAnnotation( method, HQL, SQL, FIND ) ) {

addPersistentMembers( fieldsOfClass, AccessType.FIELD );
addPersistentMembers( gettersAndSettersOfClass, AccessType.PROPERTY );

addIdClassIfNeeded( fieldsOfClass, gettersAndSettersOfClass );
}

addAuxiliaryMembers();
Expand All @@ -456,6 +460,33 @@ && containsAnnotation( method, HQL, SQL, FIND ) ) {
initialized = true;
}

private void addIdClassIfNeeded(List<? extends Element> fields, List<? extends Element> methods) {
if ( hasAnnotation( element, ID_CLASS ) ) {
return;
}
final List<MetaAttribute> components = new ArrayList<>();
for ( Element field : fields ) {
if ( hasAnnotation( field, ID ) && isPersistent( field, AccessType.FIELD ) ) {
final String propertyName = propertyName( this, field );
if ( members.containsKey( propertyName ) ) {
components.add( members.get( propertyName ) );
}
}
}
for ( Element method : methods ) {
if ( hasAnnotation( method, ID ) && isPersistent( method, AccessType.PROPERTY ) ) {
final String propertyName = propertyName( this, method );
if ( members.containsKey( propertyName ) ) {
components.add( members.get( propertyName ) );
}
}
}
if ( components.size() < 2 ) {
return;
}
putMember( ID_CLASS_MEMBER_NAME, new IdClassMetaAttribute( this, components ) );
}

private boolean checkEntities(List<ExecutableElement> lifecycleMethods) {
boolean foundPersistenceEntity = false;
VariableElement nonPersistenceParameter = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
*/
package org.hibernate.processor.annotation;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;

import org.hibernate.processor.model.MetaSingleAttribute;
import org.hibernate.processor.util.Constants;

import java.util.ArrayList;
import java.util.List;

/**
* @author Max Andersen
* @author Hardy Ferentschik
Expand All @@ -24,4 +28,9 @@ public AnnotationMetaSingleAttribute(AnnotationMetaEntity parent, Element elemen
public final String getMetaType() {
return Constants.SINGULAR_ATTRIBUTE;
}

@Override
public List<AnnotationMirror> inheritedAnnotations() {
return new ArrayList<>(element.getAnnotationMirrors());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.processor.annotation;

import org.hibernate.processor.model.MetaAttribute;
import org.hibernate.processor.model.Metamodel;

import java.util.List;

public class IdClassMetaAttribute implements MetaAttribute {

private final Metamodel parent;

private final List<MetaAttribute> components;

public IdClassMetaAttribute(Metamodel parent, List<MetaAttribute> components) {
this.parent = parent;
this.components = components;
}

@Override
public boolean hasTypedAttribute() {
return true;
}

@Override
public boolean hasStringAttribute() {
return false;
}

@Override
public String getAttributeDeclarationString() {
final StringBuilder decl = new StringBuilder()
.append("\n/**\n * Static ID class for {@link ")
.append( parent.getQualifiedName() )
.append( "}\n **/\n" )
.append( "public record Id" );
String delimiter = "(";
for ( MetaAttribute component : components ) {
decl.append( delimiter ).append( parent.importType( component.getTypeDeclaration() ) )
.append( ' ' ).append( component.getPropertyName() );
delimiter = ", ";
}
return decl.append( ") {}" ).toString();
}

@Override
public String getAttributeNameDeclarationString() {
return "";
}

@Override
public String getMetaType() {
return "";
}

@Override
public String getPropertyName() {
return "";
}

@Override
public String getTypeDeclaration() {
return "";
}

@Override
public Metamodel getHostingEntity() {
return parent;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.processor.test.hhh18829;

import jakarta.persistence.MappedSuperclass;

@MappedSuperclass
public class Address {
String address;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.processor.test.hhh18829;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class AnotherEmployee extends Address {
Integer empId;

String empName;

@Id
public Integer getEmpId() {
return empId;
}

public void setEmpId(Integer empId) {
this.empId = empId;
}

@Id
public String getEmpName() {
return empName;
}

public void setEmpName(String empName) {
this.empName = empName;
}
}
Loading
Loading