/* * 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.collection.map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.MapKeyColumn; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.collection.internal.PersistentMap; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; /** * Test various situations using a {@link PersistentMap}. * * @author Steve Ebersole * @author Brett Meyer * @author Gail Badner */ public class PersistentMapTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { return new String[] { "collection/map/Mappings.hbm.xml" }; } @Override protected Class<?>[] getAnnotatedClasses() { return new Class<?>[] { User.class, UserData.class, MultilingualString.class, MultilingualStringParent.class, Address.class, Detail.class }; } @Test @SuppressWarnings({ "unchecked" }) public void testWriteMethodDirtying() { Parent parent = new Parent( "p1" ); Child child = new Child( "c1" ); parent.getChildren().put( child.getName(), child ); child.setParent( parent ); Child otherChild = new Child( "c2" ); Session session = openSession(); session.beginTransaction(); session.save( parent ); session.flush(); // at this point, the map on parent has now been replaced with a PersistentMap... PersistentMap children = ( PersistentMap ) parent.getChildren(); Object old = children.put( child.getName(), child ); assertTrue( old == child ); assertFalse( children.isDirty() ); old = children.remove( otherChild.getName() ); assertNull( old ); assertFalse( children.isDirty() ); HashMap otherMap = new HashMap(); otherMap.put( child.getName(), child ); children.putAll( otherMap ); assertFalse( children.isDirty() ); otherMap = new HashMap(); otherMap.put( otherChild.getName(), otherChild ); children.putAll( otherMap ); assertTrue( children.isDirty() ); children.clearDirty(); session.delete( child ); children.clear(); assertTrue( children.isDirty() ); session.flush(); children.clear(); assertFalse( children.isDirty() ); session.delete( parent ); session.getTransaction().commit(); session.close(); } @Test public void testPutAgainstUninitializedMap() { // prepare map owner... Session session = openSession(); session.beginTransaction(); Parent parent = new Parent( "p1" ); session.save( parent ); session.getTransaction().commit(); session.close(); // Now, reload the parent and test adding children session = openSession(); session.beginTransaction(); parent = ( Parent ) session.get( Parent.class, parent.getName() ); parent.addChild( "c1" ); parent.addChild( "c2" ); session.getTransaction().commit(); session.close(); assertEquals( 2, parent.getChildren().size() ); session = openSession(); session.beginTransaction(); session.delete( parent ); session.getTransaction().commit(); session.close(); } @Test public void testRemoveAgainstUninitializedMap() { Parent parent = new Parent( "p1" ); Child child = new Child( "c1" ); parent.addChild( child ); Session session = openSession(); session.beginTransaction(); session.save( parent ); session.getTransaction().commit(); session.close(); // Now reload the parent and test removing the child session = openSession(); session.beginTransaction(); parent = ( Parent ) session.get( Parent.class, parent.getName() ); Child child2 = ( Child ) parent.getChildren().remove( child.getName() ); child2.setParent( null ); assertNotNull( child2 ); assertTrue( parent.getChildren().isEmpty() ); session.getTransaction().commit(); session.close(); // Load the parent once again and make sure child is still gone // then cleanup session = openSession(); session.beginTransaction(); parent = ( Parent ) session.get( Parent.class, parent.getName() ); assertTrue( parent.getChildren().isEmpty() ); session.delete( child2 ); session.delete( parent ); session.getTransaction().commit(); session.close(); } @Test @TestForIssue(jiraKey = "HHH-5732") public void testClearMap() { Session s = openSession(); s.beginTransaction(); User user = new User(); UserData userData = new UserData(); userData.user = user; user.userDatas.put( "foo", userData ); s.persist( user ); s.getTransaction().commit(); s.clear(); s.beginTransaction(); user = s.get( User.class, 1 ); user.userDatas.clear(); s.update( user ); Query q = s.createQuery( "DELETE FROM " + UserData.class.getName() + " d WHERE d.user = :user" ); q.setParameter( "user", user ); q.executeUpdate(); s.getTransaction().commit(); s.getTransaction().begin(); assertEquals( s.get( User.class, user.id ).userDatas.size(), 0 ); assertEquals( s.createQuery( "FROM " + UserData.class.getName() ).list().size(), 0 ); s.createQuery( "delete " + User.class.getName() ).executeUpdate(); s.getTransaction().commit(); s.close(); } @Test @TestForIssue( jiraKey = "HHH-5393") public void testMapKeyColumnInEmbeddableElement() { Session s = openSession(); s.getTransaction().begin(); MultilingualString m = new MultilingualString(); LocalizedString localizedString = new LocalizedString(); localizedString.setLanguage( "English" ); localizedString.setText( "name" ); m.getMap().put( localizedString.getLanguage(), localizedString ); localizedString = new LocalizedString(); localizedString.setLanguage( "English Pig Latin" ); localizedString.setText( "amenay" ); m.getMap().put( localizedString.getLanguage(), localizedString ); s.persist( m ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); m = s.get( MultilingualString.class, m.getId()); assertEquals( 2, m.getMap().size() ); localizedString = m.getMap().get( "English" ); assertEquals( "English", localizedString.getLanguage() ); assertEquals( "name", localizedString.getText() ); localizedString = m.getMap().get( "English Pig Latin" ); assertEquals( "English Pig Latin", localizedString.getLanguage() ); assertEquals( "amenay", localizedString.getText() ); s.delete( m ); s.getTransaction().commit(); s.close(); } @Test @TestForIssue( jiraKey = "HQLPARSER-15") public void testJoinFetchElementCollectionWithParentSelect() { Session s = openSession(); s.getTransaction().begin(); MultilingualString m = new MultilingualString(); LocalizedString localizedString = new LocalizedString(); localizedString.setLanguage( "English" ); localizedString.setText( "name" ); m.getMap().put( localizedString.getLanguage(), localizedString ); localizedString = new LocalizedString(); localizedString.setLanguage( "English Pig Latin" ); localizedString.setText( "amenay" ); m.getMap().put( localizedString.getLanguage(), localizedString ); MultilingualStringParent parent = new MultilingualStringParent(); parent.setString( m ); s.persist( m ); s.persist( parent ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); m = s.createQuery( "SELECT s FROM MultilingualStringParent parent " + "JOIN parent.string s " + "JOIN FETCH s.map", MultilingualString.class ) .getSingleResult(); assertEquals( 2, m.getMap().size() ); localizedString = m.getMap().get( "English" ); assertEquals( "English", localizedString.getLanguage() ); assertEquals( "name", localizedString.getText() ); localizedString = m.getMap().get( "English Pig Latin" ); assertEquals( "English Pig Latin", localizedString.getLanguage() ); assertEquals( "amenay", localizedString.getText() ); s.delete( parent ); s.delete( m ); s.getTransaction().commit(); s.close(); } @Test @TestForIssue( jiraKey = "HHH-11038" ) public void testMapKeyColumnNonInsertableNonUpdatableBidirOneToMany() { Session s = openSession(); s.getTransaction().begin(); User user = new User(); Address address = new Address(); address.addressType = "email"; address.addressText = "jane@doe.com"; user.addresses.put( address.addressType, address ); address.user = user; s.persist( user ); s.getTransaction().commit(); s.close(); s = openSession(); s.getTransaction().begin(); user = s.get( User.class, user.id ); user.addresses.clear(); s.getTransaction().commit(); s.close(); s = openSession(); s.getTransaction().begin(); user = s.get( User.class, user.id ); s.delete( user ); s.createQuery( "delete from " + User.class.getName() ).executeUpdate(); s.getTransaction().commit(); s.close(); } @Test @TestForIssue( jiraKey = "HHH-11038" ) public void testMapKeyColumnNonInsertableNonUpdatableUnidirOneToMany() { Session s = openSession(); s.getTransaction().begin(); User user = new User(); Detail detail = new Detail(); detail.description = "desc"; detail.detailType = "trivial"; user.details.put( detail.detailType, detail ); s.persist( user ); s.getTransaction().commit(); s.close(); s = openSession(); s.getTransaction().begin(); user = s.get( User.class, user.id ); user.details.clear(); s.getTransaction().commit(); s.close(); s = openSession(); s.getTransaction().begin(); user = s.get( User.class, user.id ); s.delete( user ); s.createQuery( "delete from " + User.class.getName() ).executeUpdate(); s.getTransaction().commit(); s.close(); } @Entity @Table(name = "MyUser") private static class User implements Serializable { @Id @GeneratedValue private Integer id; @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL) @MapKeyColumn(name = "name", nullable = true) private Map<String, UserData> userDatas = new HashMap<String, UserData>(); @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL) @MapKeyColumn(name = "addressType", insertable = false, updatable = false) private Map<String, Address> addresses = new HashMap<String, Address>(); @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @MapKeyColumn(name = "detailType", insertable = false, updatable = false) @JoinColumn private Map<String, Detail> details = new HashMap<String, Detail>(); } @Entity @Table(name = "UserData") private static class UserData { @Id @GeneratedValue private Integer id; @ManyToOne @JoinColumn(name = "userId") private User user; } @Entity @Table(name = "Address") private static class Address { @Id @GeneratedValue private Integer id; @ManyToOne @JoinColumn(name = "userId") private User user; @Column(nullable = false) private String addressType; @Column(nullable = false) private String addressText; } @Entity @Table(name="Detail") private static class Detail { @Id @GeneratedValue private Integer id; @Column(nullable = false) private String detailType; private String description; } }