diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/MapStringConverter.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/MapStringConverter.java new file mode 100644 index 000000000000..8f43918de57f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/MapStringConverter.java @@ -0,0 +1,39 @@ +/* + * 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.bytecode.enhancement.mutable; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import javax.persistence.AttributeConverter; + +public class MapStringConverter implements AttributeConverter, String> { + + @Override + public String convertToDatabaseColumn(Map attribute) { + if ( attribute == null ) { + return null; + } + return attribute.entrySet().stream() + .map( entry -> entry.getKey() + ";" + entry.getValue() ) + .collect( Collectors.joining( ";" ) ); + } + + @Override + public Map convertToEntityAttribute(String dbData) { + if ( dbData == null ) { + return null; + } + String[] strings = dbData.split( ";" ); + Map map = new HashMap<>(); + for ( int i = 0; i < strings.length; i += 2 ) { + map.put( strings[i], strings[i + 1] ); + } + return map; + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/MutableTypeEnhancementTestCase.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/MutableTypeEnhancementTestCase.java new file mode 100644 index 000000000000..9044b32c292b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/MutableTypeEnhancementTestCase.java @@ -0,0 +1,50 @@ +/* + * 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.bytecode.enhancement.mutable; + +import java.util.Date; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(BytecodeEnhancerRunner.class) +public class MutableTypeEnhancementTestCase extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { TestEntity.class }; + } + + @Test + @TestForIssue(jiraKey = "HHH-14329") + public void testMutateMutableTypeObject() throws Exception { + inTransaction( entityManager -> { + TestEntity e = new TestEntity(); + e.setId( 1L ); + e.setDate( new Date() ); + e.getTexts().put( "a", "abc" ); + entityManager.persist( e ); + } ); + + inTransaction( entityManager -> { + TestEntity e = entityManager.find( TestEntity.class, 1L ); + e.getDate().setTime( 0 ); + e.getTexts().put( "a", "def" ); + } ); + + inTransaction( entityManager -> { + TestEntity e = entityManager.find( TestEntity.class, 1L ); + Assert.assertEquals( 0L, e.getDate().getTime() ); + Assert.assertEquals( "def", e.getTexts().get( "a" ) ); + } ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/TestEntity.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/TestEntity.java new file mode 100644 index 000000000000..3947045b6f75 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/mutable/TestEntity.java @@ -0,0 +1,56 @@ +/* + * 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.bytecode.enhancement.mutable; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +@Entity +public class TestEntity { + @Id + private Long id; + + @Temporal(TemporalType.TIMESTAMP) + private Date date; + + @Basic + @Column(name = "TEXTS") + @Convert(converter = MapStringConverter.class) + private Map texts = new HashMap<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Map getTexts() { + return texts; + } + + public void setTexts(Map texts) { + this.texts = texts; + } +}