HHH-12124 - The JPA Metamodel does not allow to retrieve the actual EmbeddableType since all instances are registered by the associated Java type
This commit is contained in:
parent
84439af053
commit
e6ea4828db
|
@ -57,7 +57,7 @@ class MetadataContext {
|
|||
private Map<Class<?>, EntityTypeImpl<?>> entityTypes = new HashMap<>();
|
||||
private Map<String, EntityTypeImpl<?>> entityTypesByEntityName = new HashMap<>();
|
||||
private Map<PersistentClass, EntityTypeImpl<?>> entityTypesByPersistentClass = new HashMap<>();
|
||||
private Map<Class<?>, EmbeddableTypeImpl<?>> embeddables = new HashMap<>();
|
||||
private Set<EmbeddableTypeImpl<?>> embeddables = new HashSet<>();
|
||||
private Map<MappedSuperclass, MappedSuperclassTypeImpl<?>> mappedSuperclassByMappedSuperclassMapping = new HashMap<>();
|
||||
//this list contains MappedSuperclass and EntityTypes ordered by superclass first
|
||||
private List<Object> orderedMappings = new ArrayList<>();
|
||||
|
@ -93,8 +93,8 @@ class MetadataContext {
|
|||
return Collections.unmodifiableMap( entityTypes );
|
||||
}
|
||||
|
||||
public Map<Class<?>, EmbeddableTypeImpl<?>> getEmbeddableTypeMap() {
|
||||
return Collections.unmodifiableMap( embeddables );
|
||||
public Set<EmbeddableTypeImpl<?>> getEmbeddableTypeMap() {
|
||||
return Collections.unmodifiableSet( embeddables );
|
||||
}
|
||||
|
||||
public Map<Class<?>, MappedSuperclassType<?>> getMappedSuperclassTypeMap() {
|
||||
|
@ -123,7 +123,7 @@ class MetadataContext {
|
|||
}
|
||||
|
||||
/*package*/ void registerEmbeddedableType(EmbeddableTypeImpl<?> embeddableType) {
|
||||
embeddables.put( embeddableType.getJavaType(), embeddableType );
|
||||
embeddables.add( embeddableType );
|
||||
}
|
||||
|
||||
/*package*/ void registerMappedSuperclassType(
|
||||
|
@ -268,7 +268,7 @@ class MetadataContext {
|
|||
}
|
||||
|
||||
if ( staticMetamodelScanEnabled ) {
|
||||
for ( EmbeddableTypeImpl embeddable : embeddables.values() ) {
|
||||
for ( EmbeddableTypeImpl embeddable : embeddables ) {
|
||||
populateStaticMetamodel( embeddable );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.NamedAttributeNode;
|
||||
import javax.persistence.NamedEntityGraph;
|
||||
|
@ -90,6 +91,18 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable {
|
|||
|
||||
|
||||
private final Map<Class<?>, EntityTypeImpl<?>> jpaEntityTypeMap = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* There can be multiple instances of an Embeddable type, each one being relative to its parent entity.
|
||||
*/
|
||||
private final Set<EmbeddableTypeImpl<?>> jpaEmbeddableTypes = new CopyOnWriteArraySet<>();
|
||||
/**
|
||||
* That's not strictly correct in the JPA standard since for a given Java type we could have
|
||||
* multiple instances of an embeddable type. Some embeddable might override attributes, but we
|
||||
* can only return a single EmbeddableTypeImpl for a given Java object class.
|
||||
*
|
||||
* A better approach would be if the parent class and attribute name would be included as well
|
||||
* when trying to locate the embeddable type.
|
||||
*/
|
||||
private final Map<Class<?>, EmbeddableTypeImpl<?>> jpaEmbeddableTypeMap = new ConcurrentHashMap<>();
|
||||
private final Map<Class<?>, MappedSuperclassType<?>> jpaMappedSuperclassTypeMap = new ConcurrentHashMap<>();
|
||||
private final Map<String, EntityTypeImpl<?>> jpaEntityTypesByEntityName = new ConcurrentHashMap<>();
|
||||
|
@ -230,7 +243,10 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable {
|
|||
context.wrapUp();
|
||||
|
||||
this.jpaEntityTypeMap.putAll( context.getEntityTypeMap() );
|
||||
this.jpaEmbeddableTypeMap.putAll( context.getEmbeddableTypeMap() );
|
||||
this.jpaEmbeddableTypes.addAll( context.getEmbeddableTypeMap() );
|
||||
for ( EmbeddableTypeImpl<?> embeddable: jpaEmbeddableTypes ) {
|
||||
this.jpaEmbeddableTypeMap.put( embeddable.getJavaType(), embeddable );
|
||||
}
|
||||
this.jpaMappedSuperclassTypeMap.putAll( context.getMappedSuperclassTypeMap() );
|
||||
this.jpaEntityTypesByEntityName.putAll( context.getEntityTypesByEntityName() );
|
||||
|
||||
|
@ -547,12 +563,12 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable {
|
|||
@Override
|
||||
public Set<ManagedType<?>> getManagedTypes() {
|
||||
final int setSize = CollectionHelper.determineProperSizing(
|
||||
jpaEntityTypeMap.size() + jpaMappedSuperclassTypeMap.size() + jpaEmbeddableTypeMap.size()
|
||||
jpaEntityTypeMap.size() + jpaMappedSuperclassTypeMap.size() + jpaEmbeddableTypes.size()
|
||||
);
|
||||
final Set<ManagedType<?>> managedTypes = new HashSet<ManagedType<?>>( setSize );
|
||||
managedTypes.addAll( jpaEntityTypeMap.values() );
|
||||
managedTypes.addAll( jpaMappedSuperclassTypeMap.values() );
|
||||
managedTypes.addAll( jpaEmbeddableTypeMap.values() );
|
||||
managedTypes.addAll( jpaEmbeddableTypes );
|
||||
return managedTypes;
|
||||
}
|
||||
|
||||
|
@ -563,7 +579,7 @@ public class MetamodelImpl implements MetamodelImplementor, Serializable {
|
|||
|
||||
@Override
|
||||
public Set<EmbeddableType<?>> getEmbeddables() {
|
||||
return new HashSet<>( jpaEmbeddableTypeMap.values() );
|
||||
return new HashSet<>( jpaEmbeddableTypes );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.test.metamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public class Address implements Serializable {
|
||||
|
||||
private String city;
|
||||
|
||||
private String street;
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.test.metamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
|
||||
@Entity
|
||||
public class Company implements Serializable {
|
||||
|
||||
@Id
|
||||
private long id = System.nanoTime();
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Embedded
|
||||
private Address address = new Address();
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -6,19 +6,25 @@
|
|||
*/
|
||||
package org.hibernate.test.metamodel;
|
||||
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class EmbeddableMetaModelTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
ProductEntity.class
|
||||
ProductEntity.class,
|
||||
Person.class,
|
||||
Company.class
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -32,4 +38,13 @@ public class EmbeddableMetaModelTest extends BaseEntityManagerFunctionalTestCase
|
|||
} );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12124")
|
||||
public void testEmbeddableEquality() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
assertTrue( entityManager.getMetamodel().getEmbeddables().contains( Company_.address.getType() ) );
|
||||
assertTrue( entityManager.getMetamodel().getEmbeddables().contains( Person_.address.getType() ) );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.test.metamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
|
||||
@Entity
|
||||
public class Person implements Serializable {
|
||||
|
||||
@Id
|
||||
private long id = System.nanoTime();
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Embedded
|
||||
private Address address = new Address();
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue