HHH-13720 - Implement mapping model support for plural attributes

added some tests for maps
This commit is contained in:
Steve Ebersole 2019-11-21 23:58:30 -06:00
parent ecfb3da071
commit 32fd79d214
12 changed files with 1005 additions and 473 deletions

View File

@ -1082,6 +1082,24 @@ public class MappingModelCreationHelper {
return (CollectionPart) mappingType.getEmbeddedValueMapping();
}
if ( bootMapKeyDescriptor instanceof OneToMany || bootMapKeyDescriptor instanceof ToOne ) {
final EntityPersister associatedEntity;
if ( bootMapKeyDescriptor instanceof OneToMany ) {
associatedEntity = creationProcess.getEntityPersister(
( (OneToMany) bootMapKeyDescriptor ).getReferencedEntityName()
);
}
else {
// many-to-many
associatedEntity = creationProcess.getEntityPersister(
( (ToOne) bootMapKeyDescriptor ).getReferencedEntityName()
);
}
return new EntityCollectionPart( CollectionPart.Nature.ELEMENT, associatedEntity );
}
throw new NotYetImplementedFor6Exception(
"Support for plural attributes with index type [" + bootMapKeyDescriptor + "] not yet implemented"
);

View File

@ -1,461 +0,0 @@
/*
* 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.orm.test.metamodel.mapping;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.CascadeType;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.DomainMetamodel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
PluralAttributeTests.SimpleEntity.class,
PluralAttributeTests.EntityContainingLists.class,
PluralAttributeTests.EntityContainingSets.class,
PluralAttributeTests.Component.class
}
)
@ServiceRegistry
@SessionFactory
@SuppressWarnings("WeakerAccess")
public class PluralAttributeTests {
@Test
public void testLists(SessionFactoryScope scope) {
final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingLists.class );
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
final AttributeMapping listOfBasics = containerEntityDescriptor.findAttributeMapping( "listOfBasics" );
assertThat( listOfBasics, notNullValue() );
final AttributeMapping listOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "listOfConvertedBasics" );
assertThat( listOfConvertedBasics, notNullValue() );
final AttributeMapping listOfEnums = containerEntityDescriptor.findAttributeMapping( "listOfEnums" );
assertThat( listOfEnums, notNullValue() );
final AttributeMapping listOfComponents = containerEntityDescriptor.findAttributeMapping( "listOfComponents" );
assertThat( listOfComponents, notNullValue() );
final AttributeMapping listOfEntities = containerEntityDescriptor.findAttributeMapping( "listOfEntities" );
assertThat( listOfEntities, notNullValue() );
}
@Test
public void testSets(SessionFactoryScope scope) {
final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingSets.class );
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
final AttributeMapping setOfBasics = containerEntityDescriptor.findAttributeMapping( "setOfBasics" );
assertThat( setOfBasics, notNullValue() );
final AttributeMapping setOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "setOfConvertedBasics" );
assertThat( setOfConvertedBasics, notNullValue() );
final AttributeMapping setOfEnums = containerEntityDescriptor.findAttributeMapping( "setOfEnums" );
assertThat( setOfEnums, notNullValue() );
final AttributeMapping setOfComponents = containerEntityDescriptor.findAttributeMapping( "setOfComponents" );
assertThat( setOfComponents, notNullValue() );
final AttributeMapping setOfEntities = containerEntityDescriptor.findAttributeMapping( "setOfEntities" );
assertThat( setOfEntities, notNullValue() );
}
public enum EnumValue {
ONE( "first" ),
TWO( "second" ),
THREE( "third" );
private final String code;
EnumValue(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public static EnumValue fromCode(String code) {
if ( code == null || code.isEmpty() ) {
return null;
}
switch ( code ) {
case "first" : {
return ONE;
}
case "second" : {
return TWO;
}
case "third" : {
return THREE;
}
default: {
throw new RuntimeException( "Could not convert enum code : " + code );
}
}
}
}
public static class Converter implements AttributeConverter<EnumValue,String> {
@Override
public String convertToDatabaseColumn(EnumValue domainValue) {
return domainValue == null ? null : domainValue.getCode();
}
@Override
public EnumValue convertToEntityAttribute(String dbData) {
return EnumValue.fromCode( dbData );
}
}
@Entity( name = "EntityContainingLists" )
@Table( name = "entity_containing_lists" )
public static class EntityContainingLists {
private Integer id;
private String name;
private List<String> listOfBasics;
private List<EnumValue> listOfConvertedBasics;
private List<EnumValue> listOfEnums;
private List<Component> listOfComponents;
private List<SimpleEntity> listOfEntities;
public EntityContainingLists() {
}
public EntityContainingLists(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
@ElementCollection
@OrderColumn
public List<String> getListOfBasics() {
return listOfBasics;
}
public void setListOfBasics(List<String> listOfBasics) {
this.listOfBasics = listOfBasics;
}
public void addBasic(String basic) {
if ( listOfBasics == null ) {
listOfBasics = new ArrayList<>();
}
listOfBasics.add( basic );
}
@ElementCollection
@OrderColumn
@Convert( converter = Converter.class )
public List<EnumValue> getListOfConvertedBasics() {
return listOfConvertedBasics;
}
public void setListOfConvertedBasics(List<EnumValue> listOfConvertedBasics) {
this.listOfConvertedBasics = listOfConvertedBasics;
}
public void addConvertedBasic(EnumValue value) {
if ( listOfConvertedBasics == null ) {
listOfConvertedBasics = new ArrayList<>();
}
listOfConvertedBasics.add( value );
}
@ElementCollection
@Enumerated( EnumType.STRING )
@OrderColumn
public List<EnumValue> getListOfEnums() {
return listOfEnums;
}
public void setListOfEnums(List<EnumValue> listOfEnums) {
this.listOfEnums = listOfEnums;
}
public void addEnum(EnumValue value) {
if ( listOfEnums == null ) {
listOfEnums = new ArrayList<>();
}
listOfEnums.add( value );
}
@ElementCollection
@OrderColumn
public List<Component> getListOfComponents() {
return listOfComponents;
}
public void setListOfComponents(List<Component> listOfComponents) {
this.listOfComponents = listOfComponents;
}
public void addComponent(Component value) {
if ( listOfComponents == null ) {
listOfComponents = new ArrayList<>();
}
listOfComponents.add( value );
}
@OneToMany( cascade = CascadeType.ALL )
@OrderColumn
public List<SimpleEntity> getListOfEntities() {
return listOfEntities;
}
public void setListOfEntities(List<SimpleEntity> listOfEntities) {
this.listOfEntities = listOfEntities;
}
public void addSimpleEntity(SimpleEntity value) {
if ( listOfEntities == null ) {
listOfEntities = new ArrayList<>();
}
listOfEntities.add( value );
}
}
@Entity( name = "EntityContainingSets" )
@Table( name = "entity_containing_sets" )
public static class EntityContainingSets {
private Integer id;
private String name;
private Set<String> setOfBasics;
private Set<EnumValue> setOfConvertedBasics;
private Set<EnumValue> setOfEnums;
private Set<Component> setOfComponents;
private Set<SimpleEntity> setOfEntities;
public EntityContainingSets() {
}
public EntityContainingSets(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
@ElementCollection
public Set<String> getSetOfBasics() {
return setOfBasics;
}
public void setSetOfBasics(Set<String> setOfBasics) {
this.setOfBasics = setOfBasics;
}
public void addBasic(String value) {
if ( setOfBasics == null ) {
setOfBasics = new HashSet<>();
}
setOfBasics.add( value );
}
@ElementCollection
@Convert( converter = Converter.class )
public Set<EnumValue> getSetOfConvertedBasics() {
return setOfConvertedBasics;
}
public void setSetOfConvertedBasics(Set<EnumValue> setOfConvertedBasics) {
this.setOfConvertedBasics = setOfConvertedBasics;
}
public void addConvertedBasic(EnumValue value) {
if ( setOfConvertedBasics == null ) {
setOfConvertedBasics = new HashSet<>();
}
setOfConvertedBasics.add( value );
}
@ElementCollection
@Enumerated( EnumType.STRING )
public Set<EnumValue> getSetOfEnums() {
return setOfEnums;
}
public void setSetOfEnums(Set<EnumValue> setOfEnums) {
this.setOfEnums = setOfEnums;
}
public void addEnum(EnumValue value) {
if ( setOfEnums == null ) {
setOfEnums = new HashSet<>();
}
setOfEnums.add( value );
}
@ElementCollection
@Embedded
public Set<Component> getSetOfComponents() {
return setOfComponents;
}
public void setSetOfComponents(Set<Component> setOfComponents) {
this.setOfComponents = setOfComponents;
}
public void addComponent(Component value) {
if ( setOfComponents == null ) {
setOfComponents = new HashSet<>();
}
setOfComponents.add( value );
}
@OneToMany( cascade = CascadeType.ALL )
public Set<SimpleEntity> getSetOfEntities() {
return setOfEntities;
}
public void setSetOfEntities(Set<SimpleEntity> setOfEntities) {
this.setOfEntities = setOfEntities;
}
public void addSimpleEntity(SimpleEntity value) {
if ( setOfEntities == null ) {
setOfEntities = new HashSet<>();
}
setOfEntities.add( value );
}
}
@Entity( name = "SimpleEntity" )
@Table( name = "simple_entity" )
public static class SimpleEntity {
private Integer id;
private String name;
public SimpleEntity() {
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
}
@Embeddable
public static class Component {
private String anAttribute;
private String anotherAttribute;
public Component() {
}
public Component(String anAttribute, String anotherAttribute) {
this.anAttribute = anAttribute;
this.anotherAttribute = anotherAttribute;
}
public String getAnAttribute() {
return anAttribute;
}
public void setAnAttribute(String anAttribute) {
this.anAttribute = anAttribute;
}
public String getAnotherAttribute() {
return anotherAttribute;
}
public void setAnotherAttribute(String anotherAttribute) {
this.anotherAttribute = anotherAttribute;
}
}
}

View File

@ -0,0 +1,148 @@
/*
* 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.orm.test.metamodel.mapping.collections;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
/**
* @author Steve Ebersole
*/
@Entity(name = "EntityContainingLists")
@Table(name = "entity_containing_lists")
public class EntityContainingLists {
private Integer id;
private String name;
private List<String> listOfBasics;
private List<EnumValue> listOfConvertedBasics;
private List<EnumValue> listOfEnums;
private List<SomeStuff> listOfComponents;
private List<SimpleEntity> listOfEntities;
public EntityContainingLists() {
}
public EntityContainingLists(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
@ElementCollection
@OrderColumn
public List<String> getListOfBasics() {
return listOfBasics;
}
public void setListOfBasics(List<String> listOfBasics) {
this.listOfBasics = listOfBasics;
}
public void addBasic(String basic) {
if ( listOfBasics == null ) {
listOfBasics = new ArrayList<>();
}
listOfBasics.add( basic );
}
@ElementCollection
@OrderColumn
@Convert(converter = EnumValueConverter.class)
public List<EnumValue> getListOfConvertedBasics() {
return listOfConvertedBasics;
}
public void setListOfConvertedBasics(List<EnumValue> listOfConvertedBasics) {
this.listOfConvertedBasics = listOfConvertedBasics;
}
public void addConvertedBasic(EnumValue value) {
if ( listOfConvertedBasics == null ) {
listOfConvertedBasics = new ArrayList<>();
}
listOfConvertedBasics.add( value );
}
@ElementCollection
@Enumerated(EnumType.STRING)
@OrderColumn
public List<EnumValue> getListOfEnums() {
return listOfEnums;
}
public void setListOfEnums(List<EnumValue> listOfEnums) {
this.listOfEnums = listOfEnums;
}
public void addEnum(EnumValue value) {
if ( listOfEnums == null ) {
listOfEnums = new ArrayList<>();
}
listOfEnums.add( value );
}
@ElementCollection
@OrderColumn
public List<SomeStuff> getListOfComponents() {
return listOfComponents;
}
public void setListOfComponents(List<SomeStuff> listOfComponents) {
this.listOfComponents = listOfComponents;
}
public void addComponent(SomeStuff value) {
if ( listOfComponents == null ) {
listOfComponents = new ArrayList<>();
}
listOfComponents.add( value );
}
@OneToMany(cascade = CascadeType.ALL)
@OrderColumn
public List<SimpleEntity> getListOfEntities() {
return listOfEntities;
}
public void setListOfEntities(List<SimpleEntity> listOfEntities) {
this.listOfEntities = listOfEntities;
}
public void addSimpleEntity(SimpleEntity value) {
if ( listOfEntities == null ) {
listOfEntities = new ArrayList<>();
}
listOfEntities.add( value );
}
}

View File

@ -0,0 +1,206 @@
/*
* 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.orm.test.metamodel.mapping.collections;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.MapKeyColumn;
import javax.persistence.MapKeyEnumerated;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
@Entity
@Table(name = "entity_containing_maps")
public class EntityContainingMaps {
private Integer id;
private String name;
private Map<String,String> basicByBasic;
private Map<EnumValue,String> basicByEnum;
private Map<EnumValue,String> basicByConvertedEnum;
private Map<String,SomeStuff> someStuffByBasic;
private Map<SomeStuff, String> basicBySomeStuff;
private Map<String,SimpleEntity> oneToManyByBasic;
private Map<SimpleEntity,String> basicByOneToMany;
private Map<String,SimpleEntity> manyToManyByBasic;
public EntityContainingMaps() {
}
public EntityContainingMaps(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
@ElementCollection
@MapKeyColumn( name = "map_key" )
@Column( name = "map_val")
public Map<String, String> getBasicByBasic() {
return basicByBasic;
}
public void setBasicByBasic(Map<String, String> basicByBasic) {
this.basicByBasic = basicByBasic;
}
public void addBasicByBasic(String key, String val) {
if ( basicByBasic == null ) {
basicByBasic = new HashMap<>();
}
basicByBasic.put( key, val );
}
@ElementCollection
@MapKeyEnumerated
public Map<EnumValue, String> getBasicByEnum() {
return basicByEnum;
}
public void setBasicByEnum(Map<EnumValue, String> basicByEnum) {
this.basicByEnum = basicByEnum;
}
public void addBasicByEnum(EnumValue key, String val) {
if ( basicByEnum == null ) {
basicByEnum = new HashMap<>();
}
basicByEnum.put( key, val );
}
@ElementCollection
@Convert(attributeName = "key", converter = EnumValueConverter.class)
public Map<EnumValue, String> getBasicByConvertedEnum() {
return basicByConvertedEnum;
}
public void setBasicByConvertedEnum(Map<EnumValue, String> basicByConvertedEnum) {
this.basicByConvertedEnum = basicByConvertedEnum;
}
public void addBasicByConvertedEnum(EnumValue key, String value) {
if ( basicByConvertedEnum == null ) {
basicByConvertedEnum = new HashMap<>();
}
basicByConvertedEnum.put( key, value );
}
@ElementCollection
public Map<String, SomeStuff> getSomeStuffByBasic() {
return someStuffByBasic;
}
public void setSomeStuffByBasic(Map<String, SomeStuff> someStuffByBasic) {
this.someStuffByBasic = someStuffByBasic;
}
public void addSomeStuffByBasic(String key, SomeStuff value) {
if ( someStuffByBasic == null ) {
someStuffByBasic = new HashMap<>();
}
someStuffByBasic.put( key, value );
}
@ElementCollection
public Map<SomeStuff, String> getBasicBySomeStuff() {
return basicBySomeStuff;
}
public void setBasicBySomeStuff(Map<SomeStuff, String> basicBySomeStuff) {
this.basicBySomeStuff = basicBySomeStuff;
}
public void addBasicBySomeStuff(SomeStuff key, String val) {
if ( basicBySomeStuff == null ) {
basicBySomeStuff = new HashMap<>();
}
basicBySomeStuff.put( key, val );
}
@OneToMany
public Map<String, SimpleEntity> getOneToManyByBasic() {
return oneToManyByBasic;
}
public void setOneToManyByBasic(Map<String, SimpleEntity> oneToManyByBasic) {
this.oneToManyByBasic = oneToManyByBasic;
}
public void addOneToManyByBasic(String key, SimpleEntity val) {
if ( oneToManyByBasic == null ) {
oneToManyByBasic = new HashMap<>();
}
oneToManyByBasic.put( key, val );
}
// todo (6.0) : add support for using an entity as map key
// see `org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper#interpretMapKey`
@ElementCollection
public Map<SimpleEntity, String> getBasicByOneToMany() {
return basicByOneToMany;
}
public void setBasicByOneToMany(Map<SimpleEntity, String> basicByOneToMany) {
this.basicByOneToMany = basicByOneToMany;
}
public void addOneToManyByBasic(SimpleEntity key, String val) {
if ( basicByOneToMany == null ) {
basicByOneToMany = new HashMap<>();
}
basicByOneToMany.put( key, val );
}
@ManyToMany
@CollectionTable( name = "m2m_by_basic" )
public Map<String, SimpleEntity> getManyToManyByBasic() {
return manyToManyByBasic;
}
public void setManyToManyByBasic(Map<String, SimpleEntity> manyToManyByBasic) {
this.manyToManyByBasic = manyToManyByBasic;
}
public void addManyToManyByBasic(String key, SimpleEntity val) {
if ( manyToManyByBasic == null ) {
manyToManyByBasic = new HashMap<>();
}
manyToManyByBasic.put( key, val );
}
}

View File

@ -0,0 +1,144 @@
/*
* 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.orm.test.metamodel.mapping.collections;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* @author Steve Ebersole
*/
@Entity(name = "EntityContainingSets")
@Table(name = "entity_containing_sets")
public class EntityContainingSets {
private Integer id;
private String name;
private Set<String> setOfBasics;
private Set<EnumValue> setOfConvertedBasics;
private Set<EnumValue> setOfEnums;
private Set<SomeStuff> setOfComponents;
private Set<SimpleEntity> setOfEntities;
public EntityContainingSets() {
}
public EntityContainingSets(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
@ElementCollection
public Set<String> getSetOfBasics() {
return setOfBasics;
}
public void setSetOfBasics(Set<String> setOfBasics) {
this.setOfBasics = setOfBasics;
}
public void addBasic(String value) {
if ( setOfBasics == null ) {
setOfBasics = new HashSet<>();
}
setOfBasics.add( value );
}
@ElementCollection
@Convert(converter = EnumValueConverter.class)
public Set<EnumValue> getSetOfConvertedBasics() {
return setOfConvertedBasics;
}
public void setSetOfConvertedBasics(Set<EnumValue> setOfConvertedBasics) {
this.setOfConvertedBasics = setOfConvertedBasics;
}
public void addConvertedBasic(EnumValue value) {
if ( setOfConvertedBasics == null ) {
setOfConvertedBasics = new HashSet<>();
}
setOfConvertedBasics.add( value );
}
@ElementCollection
@Enumerated(EnumType.STRING)
public Set<EnumValue> getSetOfEnums() {
return setOfEnums;
}
public void setSetOfEnums(Set<EnumValue> setOfEnums) {
this.setOfEnums = setOfEnums;
}
public void addEnum(EnumValue value) {
if ( setOfEnums == null ) {
setOfEnums = new HashSet<>();
}
setOfEnums.add( value );
}
@ElementCollection
@Embedded
public Set<SomeStuff> getSetOfComponents() {
return setOfComponents;
}
public void setSetOfComponents(Set<SomeStuff> setOfComponents) {
this.setOfComponents = setOfComponents;
}
public void addComponent(SomeStuff value) {
if ( setOfComponents == null ) {
setOfComponents = new HashSet<>();
}
setOfComponents.add( value );
}
@OneToMany(cascade = CascadeType.ALL)
public Set<SimpleEntity> getSetOfEntities() {
return setOfEntities;
}
public void setSetOfEntities(Set<SimpleEntity> setOfEntities) {
this.setOfEntities = setOfEntities;
}
public void addSimpleEntity(SimpleEntity value) {
if ( setOfEntities == null ) {
setOfEntities = new HashSet<>();
}
setOfEntities.add( value );
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.orm.test.metamodel.mapping.collections;
/**
* @author Steve Ebersole
*/
public enum EnumValue {
ONE( "first" ),
TWO( "second" ),
THREE( "third" );
private final String code;
EnumValue(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public static EnumValue fromCode(String code) {
if ( code == null || code.isEmpty() ) {
return null;
}
switch ( code ) {
case "first": {
return ONE;
}
case "second": {
return TWO;
}
case "third": {
return THREE;
}
default: {
throw new RuntimeException( "Could not convert enum code : " + code );
}
}
}
}

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.orm.test.metamodel.mapping.collections;
import javax.persistence.AttributeConverter;
/**
* @author Steve Ebersole
*/
public class EnumValueConverter implements AttributeConverter<EnumValue, String> {
@Override
public String convertToDatabaseColumn(EnumValue domainValue) {
return domainValue == null ? null : domainValue.getCode();
}
@Override
public EnumValue convertToEntityAttribute(String dbData) {
return EnumValue.fromCode( dbData );
}
}

View File

@ -0,0 +1,182 @@
/*
* 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.orm.test.metamodel.mapping.collections;
import java.util.EnumSet;
import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.tool.schema.SourceType;
import org.hibernate.tool.schema.TargetType;
import org.hibernate.tool.schema.spi.CommandAcceptanceException;
import org.hibernate.tool.schema.spi.ExceptionHandler;
import org.hibernate.tool.schema.spi.ExecutionOptions;
import org.hibernate.tool.schema.spi.SchemaManagementTool;
import org.hibernate.tool.schema.spi.ScriptSourceInput;
import org.hibernate.tool.schema.spi.ScriptTargetOutput;
import org.hibernate.tool.schema.spi.SourceDescriptor;
import org.hibernate.tool.schema.spi.TargetDescriptor;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* @author Steve Ebersole
*/
@SuppressWarnings("WeakerAccess")
@DomainModel(
annotatedClasses = {
SimpleEntity.class,
EntityContainingMaps.class,
SomeStuff.class
}
)
@ServiceRegistry
@SessionFactory
public class MapOperationTests {
@BeforeEach
public void createData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final EntityContainingMaps entityContainingMaps = new EntityContainingMaps( 1, "first-map-entity" );
entityContainingMaps.addBasicByBasic( "someKey", "someValue" );
entityContainingMaps.addBasicByBasic( "anotherKey", "anotherValue" );
entityContainingMaps.addBasicByEnum( EnumValue.ONE, "one" );
entityContainingMaps.addBasicByEnum( EnumValue.TWO, "two" );
entityContainingMaps.addBasicByConvertedEnum( EnumValue.THREE, "three" );
entityContainingMaps.addSomeStuffByBasic( "the stuff", new SomeStuff( "the stuff - 1", "the stuff - 2" ) );
entityContainingMaps.addSomeStuffByBasic( "the other stuff", new SomeStuff( "the other stuff - 1", "the other stuff - 2" ) );
session.save( entityContainingMaps );
}
);
}
@AfterEach
public void dropData(SessionFactoryScope scope, DomainModelScope domainModelScope) {
// there is a problem with deleting entities which have basic collections. for some reason those
// do not register as cascadable, so we do not delete the collection rows first
// scope.inTransaction(
// session -> {
// final EntityContainingMaps entity = session.load( EntityContainingMaps.class, 1 );
// session.delete( entity );
// }
// );
// uber hacky temp way:
final ServiceRegistryImplementor serviceRegistry = scope.getSessionFactory().getServiceRegistry();
final SchemaManagementTool schemaTool = serviceRegistry.getService( SchemaManagementTool.class );
final ExecutionOptions executionOptions = new ExecutionOptions() {
@Override
public Map getConfigurationValues() {
return scope.getSessionFactory().getProperties();
}
@Override
public boolean shouldManageNamespaces() {
return false;
}
@Override
public ExceptionHandler getExceptionHandler() {
return new ExceptionHandler() {
@Override
public void handleException(CommandAcceptanceException exception) {
throw exception;
}
};
}
};
final SourceDescriptor sourceDescriptor = new SourceDescriptor() {
@Override
public SourceType getSourceType() {
return SourceType.METADATA;
}
@Override
public ScriptSourceInput getScriptSourceInput() {
return null;
}
};
final TargetDescriptor targetDescriptor = new TargetDescriptor() {
@Override
public EnumSet<TargetType> getTargetTypes() {
return EnumSet.of( TargetType.DATABASE );
}
@Override
public ScriptTargetOutput getScriptTargetOutput() {
return null;
}
};
schemaTool.getSchemaDropper( scope.getSessionFactory().getProperties() ).doDrop(
domainModelScope.getDomainModel(),
executionOptions,
sourceDescriptor,
targetDescriptor
);
schemaTool.getSchemaCreator( scope.getSessionFactory().getProperties() ).doCreation(
domainModelScope.getDomainModel(),
executionOptions,
sourceDescriptor,
targetDescriptor
);
}
@Test
public void testSqmFetching(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final EntityContainingMaps entity = session.createQuery(
"select e from EntityContainingMaps e join fetch e.basicByEnum",
EntityContainingMaps.class
).getSingleResult();
assert Hibernate.isInitialized( entity.getBasicByEnum() );
assert entity.getBasicByEnum().size() == 2;
}
);
}
@Test
@FailureExpected(
reason = "As noted in `#dropData` there is a problem with @ElementCollections not be handled properly " +
"for cascade; `org.hibernate.tuple.NonIdentifierAttribute#getCascadeStyle` returns CascadeStyles.NONE " +
"which leads to `EntityPersister#hasCascades` to report false which leads to Cascades skipping it"
)
public void testDelete(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final EntityContainingMaps entity = session.createQuery(
"select e from EntityContainingMaps e join fetch e.basicByEnum",
EntityContainingMaps.class
).getSingleResult();
session.delete( entity );
}
);
}
}

View File

@ -0,0 +1,138 @@
/*
* 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.orm.test.metamodel.mapping.collections;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.spi.DomainMetamodel;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
SimpleEntity.class,
EntityContainingLists.class,
EntityContainingSets.class,
EntityContainingMaps.class,
SomeStuff.class
}
)
@ServiceRegistry
@SessionFactory
@SuppressWarnings("WeakerAccess")
public class PluralAttributeMappingTests {
@Test
public void testLists(SessionFactoryScope scope) {
final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingLists.class );
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
final AttributeMapping listOfBasics = containerEntityDescriptor.findAttributeMapping( "listOfBasics" );
assertThat( listOfBasics, notNullValue() );
final AttributeMapping listOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "listOfConvertedBasics" );
assertThat( listOfConvertedBasics, notNullValue() );
final AttributeMapping listOfEnums = containerEntityDescriptor.findAttributeMapping( "listOfEnums" );
assertThat( listOfEnums, notNullValue() );
final AttributeMapping listOfComponents = containerEntityDescriptor.findAttributeMapping( "listOfComponents" );
assertThat( listOfComponents, notNullValue() );
final AttributeMapping listOfEntities = containerEntityDescriptor.findAttributeMapping( "listOfEntities" );
assertThat( listOfEntities, notNullValue() );
}
@Test
public void testSets(SessionFactoryScope scope) {
final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingSets.class );
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
final AttributeMapping setOfBasics = containerEntityDescriptor.findAttributeMapping( "setOfBasics" );
assertThat( setOfBasics, notNullValue() );
final AttributeMapping setOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "setOfConvertedBasics" );
assertThat( setOfConvertedBasics, notNullValue() );
final AttributeMapping setOfEnums = containerEntityDescriptor.findAttributeMapping( "setOfEnums" );
assertThat( setOfEnums, notNullValue() );
final AttributeMapping setOfComponents = containerEntityDescriptor.findAttributeMapping( "setOfComponents" );
assertThat( setOfComponents, notNullValue() );
final AttributeMapping setOfEntities = containerEntityDescriptor.findAttributeMapping( "setOfEntities" );
assertThat( setOfEntities, notNullValue() );
}
@Test
public void testMaps(SessionFactoryScope scope) {
final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingMaps.class );
// 8 for now, until entity-valued map keys is supported
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 9 ) );
final PluralAttributeMapping basicByBasic = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "basicByBasic" );
assertThat( basicByBasic, notNullValue() );
assertThat( basicByBasic.getKeyDescriptor(), notNullValue() );
assertThat( basicByBasic.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping basicByEnum = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "basicByEnum" );
assertThat( basicByEnum, notNullValue() );
assertThat( basicByEnum.getKeyDescriptor(), notNullValue() );
assertThat( basicByEnum.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping basicByConvertedEnum = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "basicByConvertedEnum" );
assertThat( basicByConvertedEnum, notNullValue() );
assertThat( basicByConvertedEnum.getKeyDescriptor(), notNullValue() );
assertThat( basicByConvertedEnum.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping someStuffByBasic = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "someStuffByBasic" );
assertThat( someStuffByBasic, notNullValue() );
assertThat( someStuffByBasic.getKeyDescriptor(), notNullValue() );
assertThat( someStuffByBasic.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping basicBySomeStuff = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "basicBySomeStuff" );
assertThat( basicBySomeStuff, notNullValue() );
assertThat( basicBySomeStuff.getKeyDescriptor(), notNullValue() );
assertThat( basicBySomeStuff.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping oneToManyByBasic = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "oneToManyByBasic" );
assertThat( oneToManyByBasic, notNullValue() );
assertThat( oneToManyByBasic.getKeyDescriptor(), notNullValue() );
assertThat( oneToManyByBasic.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping basicByOneToMany = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "basicByOneToMany" );
assertThat( basicByOneToMany, notNullValue() );
assertThat( basicByOneToMany.getKeyDescriptor(), notNullValue() );
assertThat( basicByOneToMany.getElementDescriptor(), notNullValue() );
final PluralAttributeMapping manyToManyByBasic = (PluralAttributeMapping) containerEntityDescriptor.findAttributeMapping( "manyToManyByBasic" );
assertThat( manyToManyByBasic, notNullValue() );
assertThat( manyToManyByBasic.getKeyDescriptor(), notNullValue() );
assertThat( manyToManyByBasic.getElementDescriptor(), notNullValue() );
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.orm.test.metamodel.mapping.collections;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Steve Ebersole
*/
@Entity(name = "SimpleEntity")
@Table(name = "simple_entity")
public class SimpleEntity {
private Integer id;
private String name;
public SimpleEntity() {
}
public SimpleEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
@Id
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;
}
}

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.orm.test.metamodel.mapping.collections;
import javax.persistence.Embeddable;
/**
* @author Steve Ebersole
*/
@Embeddable
public class SomeStuff {
private String anAttribute;
private String anotherAttribute;
public SomeStuff() {
}
public SomeStuff(String anAttribute, String anotherAttribute) {
this.anAttribute = anAttribute;
this.anotherAttribute = anotherAttribute;
}
public String getAnAttribute() {
return anAttribute;
}
public void setAnAttribute(String anAttribute) {
this.anAttribute = anAttribute;
}
public String getAnotherAttribute() {
return anotherAttribute;
}
public void setAnotherAttribute(String anotherAttribute) {
this.anotherAttribute = anotherAttribute;
}
}

View File

@ -10,11 +10,11 @@ import java.sql.Statement;
import org.hibernate.Hibernate;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.Component;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.EntityContainingLists;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.EntityContainingSets;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.EnumValue;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.SimpleEntity;
import org.hibernate.orm.test.metamodel.mapping.collections.SomeStuff;
import org.hibernate.orm.test.metamodel.mapping.collections.EntityContainingLists;
import org.hibernate.orm.test.metamodel.mapping.collections.EntityContainingSets;
import org.hibernate.orm.test.metamodel.mapping.collections.EnumValue;
import org.hibernate.orm.test.metamodel.mapping.collections.SimpleEntity;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.testing.orm.junit.DomainModel;
@ -25,8 +25,6 @@ import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
@ -40,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
SimpleEntity.class,
EntityContainingLists.class,
EntityContainingSets.class,
Component.class
SomeStuff.class
}
)
@ServiceRegistry
@ -143,8 +141,8 @@ public class PluralAttributeSmokeTests {
entityContainingLists.addEnum( EnumValue.ONE );
entityContainingLists.addEnum( EnumValue.THREE );
entityContainingLists.addComponent( new Component( "first-a1", "first-another-a1" ) );
entityContainingLists.addComponent( new Component( "first-a2", "first-another-a2" ) );
entityContainingLists.addComponent( new SomeStuff( "first-a1", "first-another-a1" ) );
entityContainingLists.addComponent( new SomeStuff( "first-a2", "first-another-a2" ) );
entityContainingLists.addSimpleEntity( simpleEntity1 );
entityContainingLists.addSimpleEntity( simpleEntity2 );
@ -164,8 +162,8 @@ public class PluralAttributeSmokeTests {
entity.addEnum( EnumValue.ONE );
entity.addEnum( EnumValue.THREE );
entity.addComponent( new Component( "first-a1", "first-another-a1" ) );
entity.addComponent( new Component( "first-a2", "first-another-a2" ) );
entity.addComponent( new SomeStuff( "first-a1", "first-another-a1" ) );
entity.addComponent( new SomeStuff( "first-a2", "first-another-a2" ) );
entity.addSimpleEntity( simpleEntity1 );
entity.addSimpleEntity( simpleEntity2 );