HHH-12581 - Added test case.

(cherry picked from commit 3b05e92)
This commit is contained in:
Chris Cranford 2018-05-23 13:53:46 -04:00
parent 940b771f96
commit e66d0689b4
14 changed files with 511 additions and 18 deletions

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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() );
} );
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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"
);
}
}

View File

@ -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;
}
}

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.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;
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}
}

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.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;
}
}

View File

@ -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
);
}
}