HHH-12581 - Added test case.
This commit is contained in:
parent
367cc4c33d
commit
3b05e92f40
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public interface Attribute {
|
||||
String getType();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Embeddable
|
||||
public class Color implements Attribute {
|
||||
public static String TYPE = "Color";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public class ElementCollectionConverterTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { Item.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12581")
|
||||
public void testCriteriaQueryWithElementCollectionUsingConverter() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Item item1 = new Item( "P1" );
|
||||
item1.getRoles().add( new Color() );
|
||||
|
||||
Item item2 = new Item( "P2" );
|
||||
item2.getRoles().add( new Industry() );
|
||||
|
||||
Item item3 = new Item( "P3" );
|
||||
item3.getRoles().add( new Color() );
|
||||
item3.getRoles().add( new Industry() );
|
||||
|
||||
entityManager.persist( item1 );
|
||||
entityManager.persist( item2 );
|
||||
entityManager.persist( item3 );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Item> query = cb.createQuery( Item.class );
|
||||
Root<Item> root = query.from( Item.class );
|
||||
|
||||
// HHH-12338 effectively caused Item_.roles to be null.
|
||||
// Therefore this caused a NPE with the commit originally applied for HHH-12338.
|
||||
// Reverting that fix avoids the regression and this proceeds as expected.
|
||||
root.fetch( Item_.roles );
|
||||
|
||||
// Just running the query here.
|
||||
// the outcome is less important than the above for context of this test case.
|
||||
query = query.select( root ).distinct( true );
|
||||
List<Item> items = entityManager.createQuery( query ).getResultList();
|
||||
assertEquals( 3, items.size() );
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Embeddable
|
||||
public class Industry implements Attribute {
|
||||
public static String TYPE = "Industry";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Entity
|
||||
public class Item {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "item_roles")
|
||||
@Convert(converter = ItemAttributeConverter.class)
|
||||
public List<Attribute> roles = new ArrayList<>();
|
||||
|
||||
Item() {
|
||||
|
||||
}
|
||||
|
||||
Item(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Attribute> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<Attribute> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.jpa.test.criteria;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public class ItemAttributeConverter implements AttributeConverter<Attribute, String> {
|
||||
private static Map<String, Class<? extends Attribute>> attributeMap;
|
||||
|
||||
static {
|
||||
attributeMap = new HashMap<>();
|
||||
attributeMap.put( Color.TYPE, Color.class );
|
||||
attributeMap.put( Industry.TYPE, Industry.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(Attribute attribute) {
|
||||
return attribute == null ? null : attribute.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attribute convertToEntityAttribute(String s) {
|
||||
try {
|
||||
Class<? extends Attribute> attributeClass = attributeMap.get( s );
|
||||
return attributeClass == null ? null : attributeClass.newInstance();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
// ignore
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
||||
import org.hibernate.jpamodelgen.test.util.TestForIssue;
|
||||
import org.hibernate.jpamodelgen.test.util.WithClasses;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertListAttributeTypeInMetaModelFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMapAttributesInMetaModelFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertSetAttributeTypeInMetaModelFor;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public class ElementCollectionWithConverterTest extends CompilationTest {
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12581")
|
||||
@WithClasses( { Item.class } )
|
||||
public void testConverterAppliedToElementCollections() {
|
||||
assertMetamodelClassGeneratedFor( Item.class );
|
||||
|
||||
// Verify that field roles is a SetAttribute with a generic type of Role.class
|
||||
assertSetAttributeTypeInMetaModelFor(
|
||||
Item.class,
|
||||
"roles",
|
||||
Role.class,
|
||||
"Generic types or attribute class implementation incorrect for property roles"
|
||||
);
|
||||
|
||||
// Verify that field providers is a ListAttribute with a generic type of String.class
|
||||
assertListAttributeTypeInMetaModelFor(
|
||||
Item.class,
|
||||
"providers",
|
||||
String.class,
|
||||
"Generic types or attribute class implementation incorrect for property providers"
|
||||
);
|
||||
|
||||
// Verify that field attributes is a MapAttribute with a generic type of
|
||||
// String.class for the value and Integer.class for the key
|
||||
assertMapAttributesInMetaModelFor(
|
||||
Item.class,
|
||||
"attributes",
|
||||
Integer.class,
|
||||
String.class,
|
||||
"Generic types or attribute class implementation incorrect for property attributes"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Entity
|
||||
public class Item {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@ElementCollection
|
||||
@Convert(converter = ItemRoleConverter.class)
|
||||
private Set<Role> roles = new HashSet<>();
|
||||
|
||||
@ElementCollection
|
||||
@Convert(converter = StringToUppercaseConverter.class)
|
||||
private List<String> providers = new ArrayList<>();
|
||||
|
||||
@ElementCollection
|
||||
@Convert(converter = StringToUppercaseConverter.class)
|
||||
private Map<Integer, String> attributes = new HashMap<>();
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Role> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(Set<Role> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public List<String> getProviders() {
|
||||
return providers;
|
||||
}
|
||||
|
||||
public void setProviders(List<String> providers) {
|
||||
this.providers = providers;
|
||||
}
|
||||
|
||||
public Map<Integer, String> getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public void setAttributes(Map<Integer, String> attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
}
|
|
@ -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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public class ItemRoleConverter implements AttributeConverter<Role, String> {
|
||||
@Override
|
||||
public String convertToDatabaseColumn(Role role) {
|
||||
return role == null ? null : role.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role convertToEntityAttribute(String s) {
|
||||
if ( s != null ) {
|
||||
if ( RoleInternal.TYPE.equals( s ) ) {
|
||||
return new RoleInternal();
|
||||
}
|
||||
else if ( RoleExternal.TYPE.equals( s ) ) {
|
||||
return new RoleExternal();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public interface Role {
|
||||
String getType();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Embeddable
|
||||
public class RoleExternal implements Role {
|
||||
public static String TYPE = "External";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@Embeddable
|
||||
public class RoleInternal implements Role {
|
||||
public static String TYPE = "Internal";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
|
@ -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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
/**
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
public class StringToUppercaseConverter implements AttributeConverter<String, String> {
|
||||
@Override
|
||||
public String convertToDatabaseColumn(String s) {
|
||||
return s == null ? null : s.toUpperCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToEntityAttribute(String s) {
|
||||
return s;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import java.net.URL;
|
|||
import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
import javax.persistence.metamodel.ListAttribute;
|
||||
import javax.persistence.metamodel.SetAttribute;
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -113,25 +114,12 @@ public class TestUtil {
|
|||
);
|
||||
}
|
||||
|
||||
public static void assertSetAttributeTypeInMetaModelFor(Class<?> clazz, String fieldName, Class<?> expectedType, String errorString) {
|
||||
assertCollectionAttributeTypeInMetaModelFor( clazz, fieldName, SetAttribute.class, expectedType, errorString );
|
||||
}
|
||||
|
||||
public static void assertListAttributeTypeInMetaModelFor(Class<?> clazz, String fieldName, Class<?> expectedType, String errorString) {
|
||||
Field field = getFieldFromMetamodelFor( clazz, fieldName );
|
||||
assertNotNull( "Cannot find field '" + fieldName + "' in " + clazz.getName(), field );
|
||||
ParameterizedType type = (ParameterizedType) field.getGenericType();
|
||||
Type rawType = type.getRawType();
|
||||
|
||||
assertEquals(
|
||||
"Types do not match: " + buildErrorString( errorString, clazz ),
|
||||
ListAttribute.class,
|
||||
rawType
|
||||
);
|
||||
|
||||
Type genericType = type.getActualTypeArguments()[1];
|
||||
|
||||
assertEquals(
|
||||
"Types do not match: " + buildErrorString( errorString, clazz ),
|
||||
expectedType,
|
||||
genericType
|
||||
);
|
||||
assertCollectionAttributeTypeInMetaModelFor( clazz, fieldName, ListAttribute.class, expectedType, errorString );
|
||||
}
|
||||
|
||||
public static void assertMapAttributesInMetaModelFor(Class<?> clazz, String fieldName, Class<?> expectedMapKey, Class<?> expectedMapValue, String errorString) {
|
||||
|
@ -351,6 +339,33 @@ public class TestUtil {
|
|||
}
|
||||
return targetDir;
|
||||
}
|
||||
|
||||
private static void assertCollectionAttributeTypeInMetaModelFor(
|
||||
Class<?> clazz,
|
||||
String fieldName,
|
||||
Class<?> collectionType,
|
||||
Class<?> expectedType,
|
||||
String errorString) {
|
||||
Field field = getFieldFromMetamodelFor( clazz, fieldName );
|
||||
assertNotNull( "Cannot find field '" + fieldName + "' in " + clazz.getName(), field );
|
||||
ParameterizedType type = (ParameterizedType) field.getGenericType();
|
||||
Type rawType = type.getRawType();
|
||||
|
||||
assertEquals(
|
||||
"Types do not match: " + buildErrorString( errorString, clazz ),
|
||||
collectionType,
|
||||
rawType
|
||||
);
|
||||
|
||||
Type genericType = type.getActualTypeArguments()[1];
|
||||
|
||||
assertEquals(
|
||||
"Types do not match: " + buildErrorString( errorString, clazz ),
|
||||
expectedType,
|
||||
genericType
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue