/*
* 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.elementCollection;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Converts;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.IndexedCollection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Test for {@link org.hibernate.cfg.CollectionPropertyHolder}.
*
* Tests that {@link javax.persistence.AttributeConverter}s are considered correctly for {@link javax.persistence.ElementCollection}.
*
* @author Markus Heiden
* @author Steve Ebersole
*/
@TestForIssue( jiraKey = "HHH-9495" )
public class ElementCollectionTests extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { TheEntity.class };
}
@Test
public void testSimpleConvertUsage() throws MalformedURLException {
// first some assertions of the metamodel
PersistentClass entityBinding = metadata().getEntityBinding( TheEntity.class.getName() );
assertNotNull( entityBinding );
Property setAttributeBinding = entityBinding.getProperty( "set" );
Collection setBinding = (Collection) setAttributeBinding.getValue();
assertTyping( AttributeConverterTypeAdapter.class, setBinding.getElement().getType() );
Property mapAttributeBinding = entityBinding.getProperty( "map" );
IndexedCollection mapBinding = (IndexedCollection) mapAttributeBinding.getValue();
assertTyping( AttributeConverterTypeAdapter.class, mapBinding.getIndex().getType() );
assertTyping( AttributeConverterTypeAdapter.class, mapBinding.getElement().getType() );
// now lets try to use the model, integration-testing-style!
TheEntity entity = new TheEntity(1);
Session s = openSession();
s.beginTransaction();
s.save( entity );
s.getTransaction().commit();
s.close();
s = openSession();
s.beginTransaction();
TheEntity retrieved = (TheEntity) s.load( TheEntity.class, 1 );
assertEquals( 1, retrieved.getSet().size() );
assertEquals(new ValueType("set_value"), retrieved.getSet().iterator().next());
assertEquals(1, retrieved.getMap().size());
assertEquals(new ValueType("map_value"), retrieved.getMap().get(new ValueType("map_key")));
s.delete( retrieved );
s.getTransaction().commit();
s.close();
}
/**
* Non-serializable value type.
*/
public static class ValueType {
private final String value;
public ValueType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public boolean equals(Object o) {
return o instanceof ValueType &&
value.equals(((ValueType) o).value);
}
@Override
public int hashCode() {
return value.hashCode();
}
}
/**
* Converter for {@link ValueType}.
*/
public static class ValueTypeConverter implements AttributeConverter<ValueType, String> {
@Override
public String convertToDatabaseColumn(ValueType type) {
return type.getValue();
}
@Override
public ValueType convertToEntityAttribute(String type) {
return new ValueType(type);
}
}
/**
* Entity holding element collections.
*/
@Entity( name = "TheEntity" )
@Table(name = "entity")
public static class TheEntity {
@Id
public Integer id;
/**
* Element set with converter.
*/
@Convert( converter = ValueTypeConverter.class )
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "entity_set", joinColumns = @JoinColumn(name = "entity_id", nullable = false))
@Column(name = "value", nullable = false)
public Set<ValueType> set = new HashSet<ValueType>();
/**
* Element map with converters.
*/
@Converts({
@Convert(attributeName = "key", converter = ValueTypeConverter.class),
@Convert(attributeName = "value", converter = ValueTypeConverter.class)
})
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "entity_map", joinColumns = @JoinColumn(name = "entity_id", nullable = false))
@MapKeyColumn(name = "map_key", nullable = false)
@Column(name = "value", nullable = false)
public Map<ValueType, ValueType> map = new HashMap<ValueType, ValueType>();
public TheEntity() {
}
public TheEntity(Integer id) {
this.id = id;
this.set.add(new ValueType("set_value"));
this.map.put( new ValueType( "map_key" ), new ValueType( "map_value" ) );
}
public Set<ValueType> getSet() {
return set;
}
public Map<ValueType, ValueType> getMap() {
return map;
}
}
}