/* * 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.converter.map; import java.util.HashMap; import java.util.Map; import javax.persistence.AttributeConverter; import javax.persistence.CascadeType; import javax.persistence.Convert; import javax.persistence.Converter; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MapKey; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.Transaction; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * @author Janario Oliveira */ public class MapKeyAttributeConverterTest extends BaseNonConfigCoreFunctionalTestCase { @Override protected Class[] getAnnotatedClasses() { return new Class[] { MapEntity.class, MapValue.class, ColorTypeConverter.class, CustomColorTypeConverter.class, ImplicitEnumMapKeyConverter.class, ExplicitEnumMapKeyConverter.class, ImplicitEnumMapKeyOverridedConverter.class }; } @Test public void testImplicitType() { MapValue mapValue = create(); mapValue.implicitType = ColorType.BLUE; mapValue.mapEntity.implicitType.put( mapValue.implicitType, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.implicitType.size() ); MapValue foundValue = found.implicitType.get( ColorType.BLUE ); assertEquals( ColorType.BLUE, foundValue.implicitType ); assertEquals( "blue", findDatabaseValue( foundValue, "implicitType" ) ); getSession().close(); } @Test public void testExplicitType() { MapValue mapValue = create(); mapValue.explicitType = ColorType.RED; mapValue.mapEntity.explicitType.put( mapValue.explicitType, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.explicitType.size() ); MapValue foundValue = found.explicitType.get( ColorType.RED ); assertEquals( ColorType.RED, foundValue.explicitType ); assertEquals( "COLOR-red", findDatabaseValue( foundValue, "explicitType" ) ); getSession().close(); } @Test public void testEnumDefaultType() { MapValue mapValue = create(); mapValue.enumDefault = EnumMapKey.VALUE_1; mapValue.mapEntity.enumDefaultType.put( mapValue.enumDefault, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumDefaultType.size() ); MapValue foundValue = found.enumDefaultType.get( EnumMapKey.VALUE_1 ); assertEquals( EnumMapKey.VALUE_1, foundValue.enumDefault ); assertEquals( 0, ((Number) findDatabaseValue( foundValue, "enumDefault" )).intValue() ); getSession().close(); } @Test public void testEnumExplicitOrdinalType() { MapValue mapValue = create(); mapValue.enumExplicitOrdinal = EnumMapKey.VALUE_2; mapValue.mapEntity.enumExplicitOrdinalType.put( mapValue.enumExplicitOrdinal, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumExplicitOrdinalType.size() ); MapValue foundValue = found.enumExplicitOrdinalType.get( EnumMapKey.VALUE_2 ); assertEquals( EnumMapKey.VALUE_2, foundValue.enumExplicitOrdinal ); assertEquals( 1, ((Number) findDatabaseValue( foundValue, "enumExplicitOrdinal" )).intValue() ); getSession().close(); } @Test public void testEnumExplicitStringType() { MapValue mapValue = create(); mapValue.enumExplicitString = EnumMapKey.VALUE_1; mapValue.mapEntity.enumExplicitStringType.put( mapValue.enumExplicitString, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumExplicitStringType.size() ); MapValue foundValue = found.enumExplicitStringType.get( EnumMapKey.VALUE_1 ); assertEquals( EnumMapKey.VALUE_1, foundValue.enumExplicitString ); assertEquals( "VALUE_1", findDatabaseValue( foundValue, "enumExplicitString" ) ); getSession().close(); } @Test public void testEnumExplicitType() { MapValue mapValue = create(); mapValue.enumExplicit = EnumMapKey.VALUE_2; mapValue.mapEntity.enumExplicitType.put( mapValue.enumExplicit, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumExplicitType.size() ); MapValue foundValue = found.enumExplicitType.get( EnumMapKey.VALUE_2 ); assertEquals( EnumMapKey.VALUE_2, foundValue.enumExplicit ); assertEquals( "2", findDatabaseValue( foundValue, "enumExplicit" ) ); getSession().close(); } @Test public void testEnumImplicitType() { MapValue mapValue = create(); mapValue.enumImplicit = ImplicitEnumMapKey.VALUE_2; mapValue.mapEntity.enumImplicitType.put( mapValue.enumImplicit, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumImplicitType.size() ); MapValue foundValue = found.enumImplicitType.get( ImplicitEnumMapKey.VALUE_2 ); assertEquals( ImplicitEnumMapKey.VALUE_2, foundValue.enumImplicit ); assertEquals( "I2", findDatabaseValue( foundValue, "enumImplicit" ) ); getSession().close(); } @Test public void testEnumImplicitOverrideOrdinalType() { MapValue mapValue = create(); mapValue.enumImplicitOverrideOrdinal = ImplicitEnumMapKey.VALUE_1; mapValue.mapEntity.enumImplicitOverrideOrdinalType.put( mapValue.enumImplicitOverrideOrdinal, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumImplicitOverrideOrdinalType.size() ); MapValue foundValue = found.enumImplicitOverrideOrdinalType.get( ImplicitEnumMapKey.VALUE_1 ); assertEquals( ImplicitEnumMapKey.VALUE_1, foundValue.enumImplicitOverrideOrdinal ); assertEquals( 0, ((Number) findDatabaseValue( foundValue, "enumImplicitOverrideOrdinal" )).intValue() ); getSession().close(); } @Test public void testEnumImplicitOverrideStringType() { MapValue mapValue = create(); mapValue.enumImplicitOverrideString = ImplicitEnumMapKey.VALUE_2; mapValue.mapEntity.enumImplicitOverrideStringType.put( mapValue.enumImplicitOverrideString, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumImplicitOverrideStringType.size() ); MapValue foundValue = found.enumImplicitOverrideStringType.get( ImplicitEnumMapKey.VALUE_2 ); assertEquals( ImplicitEnumMapKey.VALUE_2, foundValue.enumImplicitOverrideString ); assertEquals( "VALUE_2", findDatabaseValue( foundValue, "enumImplicitOverrideString" ) ); getSession().close(); } @Test public void testEnumImplicitOverridedType() { MapValue mapValue = create(); mapValue.enumImplicitOverrided = ImplicitEnumMapKey.VALUE_1; mapValue.mapEntity.enumImplicitOverridedType.put( mapValue.enumImplicitOverrided, mapValue ); MapEntity found = persist( mapValue.mapEntity ); assertEquals( 1, found.enumImplicitOverridedType.size() ); MapValue foundValue = found.enumImplicitOverridedType.get( ImplicitEnumMapKey.VALUE_1 ); assertEquals( ImplicitEnumMapKey.VALUE_1, foundValue.enumImplicitOverrided ); assertEquals( "O1", findDatabaseValue( foundValue, "enumImplicitOverrided" ) ); getSession().close(); } private MapValue create() { MapEntity mapEntity = new MapEntity(); return new MapValue( mapEntity ); } private MapEntity persist(MapEntity mapEntity) { Transaction tx = openSession().getTransaction(); tx.begin(); mapEntity = (MapEntity) getSession().merge( mapEntity ); tx.commit(); getSession().close(); mapEntity = openSession().get( MapEntity.class, mapEntity.id ); return mapEntity; } private Object findDatabaseValue(MapValue mapValue, String column) { return getSession() .createSQLQuery( "select mv." + column + " from map_value mv where mv.id=:id" ) .setParameter( "id", mapValue.id ) .uniqueResult(); } @Entity @Table(name = "map_entity") public static class MapEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "implicitType") private Map<ColorType, MapValue> implicitType = new HashMap<ColorType, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "explicitType") private Map<ColorType, MapValue> explicitType = new HashMap<ColorType, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumDefault") private Map<EnumMapKey, MapValue> enumDefaultType = new HashMap<EnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumExplicitOrdinal") private Map<EnumMapKey, MapValue> enumExplicitOrdinalType = new HashMap<EnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumExplicitString") private Map<EnumMapKey, MapValue> enumExplicitStringType = new HashMap<EnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumExplicit") private Map<EnumMapKey, MapValue> enumExplicitType = new HashMap<EnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumImplicit") private Map<ImplicitEnumMapKey, MapValue> enumImplicitType = new HashMap<ImplicitEnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumImplicitOverrideOrdinal") private Map<ImplicitEnumMapKey, MapValue> enumImplicitOverrideOrdinalType = new HashMap<ImplicitEnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumImplicitOverrideString") private Map<ImplicitEnumMapKey, MapValue> enumImplicitOverrideStringType = new HashMap<ImplicitEnumMapKey, MapValue>(); @OneToMany(mappedBy = "mapEntity", cascade = CascadeType.ALL) @MapKey(name = "enumImplicitOverrided") private Map<ImplicitEnumMapKey, MapValue> enumImplicitOverridedType = new HashMap<ImplicitEnumMapKey, MapValue>(); } @Entity @Table(name = "map_value") public static class MapValue { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @ManyToOne @JoinColumn(name = "map_entity_id") private MapEntity mapEntity; private ColorType implicitType; @Convert(converter = CustomColorTypeConverter.class) private ColorType explicitType; private EnumMapKey enumDefault; @Enumerated private EnumMapKey enumExplicitOrdinal; @Enumerated(EnumType.STRING) private EnumMapKey enumExplicitString; @Convert(converter = ExplicitEnumMapKeyConverter.class) private EnumMapKey enumExplicit; private ImplicitEnumMapKey enumImplicit; @Enumerated private ImplicitEnumMapKey enumImplicitOverrideOrdinal; @Enumerated(EnumType.STRING) private ImplicitEnumMapKey enumImplicitOverrideString; @Convert(converter = ImplicitEnumMapKeyOverridedConverter.class) private ImplicitEnumMapKey enumImplicitOverrided; protected MapValue() { } public MapValue(MapEntity mapEntity) { this.mapEntity = mapEntity; } } public enum EnumMapKey { VALUE_1, VALUE_2 } public enum ImplicitEnumMapKey { VALUE_1, VALUE_2 } @Converter public static class CustomColorTypeConverter implements AttributeConverter<ColorType, String> { @Override public String convertToDatabaseColumn(ColorType attribute) { return attribute == null ? null : "COLOR-" + attribute.toExternalForm(); } @Override public ColorType convertToEntityAttribute(String dbData) { return dbData == null ? null : ColorType.fromExternalForm( dbData.substring( 6 ) ); } } @Converter public static class ExplicitEnumMapKeyConverter implements AttributeConverter<EnumMapKey, String> { @Override public String convertToDatabaseColumn(EnumMapKey attribute) { return attribute == null ? null : attribute.name().substring( attribute.name().length() - 1 ); } @Override public EnumMapKey convertToEntityAttribute(String dbData) { return dbData == null ? null : EnumMapKey.valueOf( "VALUE_" + dbData ); } } @Converter(autoApply = true) public static class ImplicitEnumMapKeyConverter implements AttributeConverter<ImplicitEnumMapKey, String> { @Override public String convertToDatabaseColumn(ImplicitEnumMapKey attribute) { return attribute == null ? null : "I" + attribute.name().substring( attribute.name().length() - 1 ); } @Override public ImplicitEnumMapKey convertToEntityAttribute(String dbData) { return dbData == null ? null : ImplicitEnumMapKey.valueOf( "VALUE_" + dbData.substring( 1 ) ); } } @Converter public static class ImplicitEnumMapKeyOverridedConverter implements AttributeConverter<ImplicitEnumMapKey, String> { @Override public String convertToDatabaseColumn(ImplicitEnumMapKey attribute) { return attribute == null ? null : ( "O" + attribute.name().substring( attribute.name().length() - 1 ) ); } @Override public ImplicitEnumMapKey convertToEntityAttribute(String dbData) { return dbData == null ? null : ImplicitEnumMapKey.valueOf( "VALUE_" + dbData.substring( 1 ) ); } } }