/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2011, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.hibernate.test.annotations.indexcoll; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.HSQLDialect; import org.hibernate.mapping.Collection; import org.hibernate.mapping.Column; import org.junit.Test; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; 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; /** * Test index collections * * @author Emmanuel Bernard */ public class IndexedCollectionTest extends BaseCoreFunctionalTestCase { @Test public void testJPA2DefaultMapColumns() throws Exception { isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesDef", "_KEY" ); isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesPerKeyDef", "_KEY" ); isDefaultKeyColumnPresent( Atmosphere.class.getName(), "gasesDefLeg", "_KEY" ); } @Test public void testJPA2DefaultIndexColumns() throws Exception { isDefaultKeyColumnPresent( Drawer.class.getName(), "dresses", "_ORDER" ); } private void isDefaultKeyColumnPresent(String collectionOwner, String propertyName, String suffix) { assertTrue( "Could not find " + propertyName + suffix, isDefaultColumnPresent(collectionOwner, propertyName, suffix) ); } private boolean isDefaultColumnPresent(String collectionOwner, String propertyName, String suffix) { final Collection collection = configuration().getCollectionMapping( collectionOwner + "." + propertyName ); final Iterator columnIterator = collection.getCollectionTable().getColumnIterator(); boolean hasDefault = false; while ( columnIterator.hasNext() ) { Column column = (Column) columnIterator.next(); if ( (propertyName + suffix).equals( column.getName() ) ) hasDefault = true; } return hasDefault; } private void isNotDefaultKeyColumnPresent(String collectionOwner, String propertyName, String suffix) { assertFalse( "Could not find " + propertyName + suffix, isDefaultColumnPresent(collectionOwner, propertyName, suffix) ); } @Test public void testFkList() throws Exception { Wardrobe w = new Wardrobe(); Drawer d1 = new Drawer(); Drawer d2 = new Drawer(); w.setDrawers( new ArrayList<Drawer>() ); w.getDrawers().add( d1 ); w.getDrawers().add( d2 ); Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); s.persist( w ); s.flush(); s.clear(); w = (Wardrobe) s.get( Wardrobe.class, w.getId() ); assertNotNull( w ); assertNotNull( w.getDrawers() ); List<Drawer> result = w.getDrawers(); assertEquals( 2, result.size() ); assertEquals( d2.getId(), result.get( 1 ).getId() ); result.remove( d1 ); s.flush(); d1 = (Drawer) s.merge( d1 ); result.add( d1 ); s.flush(); s.clear(); w = (Wardrobe) s.get( Wardrobe.class, w.getId() ); assertNotNull( w ); assertNotNull( w.getDrawers() ); result = w.getDrawers(); assertEquals( 2, result.size() ); assertEquals( d1.getId(), result.get( 1 ).getId() ); s.delete( result.get( 0 ) ); s.delete( result.get( 1 ) ); s.delete( w ); s.flush(); tx.rollback(); s.close(); } @Test public void testJoinedTableList() throws Exception { Wardrobe w = new Wardrobe(); w.setDrawers( new ArrayList<Drawer>() ); Drawer d = new Drawer(); w.getDrawers().add( d ); Dress d1 = new Dress(); Dress d2 = new Dress(); d.setDresses( new ArrayList<Dress>() ); d.getDresses().add( d1 ); d.getDresses().add( d2 ); Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); s.persist( d1 ); s.persist( d2 ); s.persist( w ); s.flush(); s.clear(); d = (Drawer) s.get( Drawer.class, d.getId() ); assertNotNull( d ); assertNotNull( d.getDresses() ); List<Dress> result = d.getDresses(); assertEquals( 2, result.size() ); assertEquals( d2.getId(), result.get( 1 ).getId() ); result.remove( d1 ); s.flush(); d1 = (Dress) s.merge( d1 ); result.add( d1 ); s.flush(); s.clear(); d = (Drawer) s.get( Drawer.class, d.getId() ); assertNotNull( d ); assertNotNull( d.getDresses() ); result = d.getDresses(); assertEquals( 2, result.size() ); assertEquals( d1.getId(), result.get( 1 ).getId() ); s.delete( result.get( 0 ) ); s.delete( result.get( 1 ) ); s.delete( d ); s.flush(); tx.rollback(); s.close(); } @Test public void testMapKey() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); Software hibernate = new Software(); hibernate.setName( "Hibernate" ); Version v1 = new Version(); v1.setCodeName( "HumbaHumba" ); v1.setNumber( "1.0" ); v1.setSoftware( hibernate ); Version v2 = new Version(); v2.setCodeName( "Copacabana" ); v2.setNumber( "2.0" ); v2.setSoftware( hibernate ); Version v4 = new Version(); v4.setCodeName( "Dreamland" ); v4.setNumber( "4.0" ); v4.setSoftware( hibernate ); Map<String, Version> link = new HashMap<String, Version>(); link.put( v1.getCodeName(), v1 ); link.put( v2.getCodeName(), v2 ); link.put( v4.getCodeName(), v4 ); hibernate.setVersions( link ); s.persist( hibernate ); s.persist( v1 ); s.persist( v2 ); s.persist( v4 ); s.flush(); s.clear(); hibernate = (Software) s.get( Software.class, "Hibernate" ); assertEquals( 3, hibernate.getVersions().size() ); assertEquals( "1.0", hibernate.getVersions().get( "HumbaHumba" ).getNumber() ); assertEquals( "2.0", hibernate.getVersions().get( "Copacabana" ).getNumber() ); hibernate.getVersions().remove( v4.getCodeName() ); s.flush(); s.clear(); hibernate = (Software) s.get( Software.class, "Hibernate" ); assertEquals( "So effect on collection changes", 3, hibernate.getVersions().size() ); for ( Version v : hibernate.getVersions().values() ) { s.delete( v ); } s.delete( hibernate ); s.flush(); tx.rollback(); s.close(); } @Test public void testDefaultMapKey() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); AddressBook book = new AddressBook(); book.setOwner( "Emmanuel" ); AddressEntryPk helene = new AddressEntryPk( "Helene", "Michau" ); AddressEntry heleneEntry = new AddressEntry(); heleneEntry.setBook( book ); heleneEntry.setCity( "Levallois" ); heleneEntry.setStreet( "Louis Blanc" ); heleneEntry.setPerson( helene ); AddressEntryPk primeMinister = new AddressEntryPk( "Dominique", "Villepin" ); AddressEntry primeMinisterEntry = new AddressEntry(); primeMinisterEntry.setBook( book ); primeMinisterEntry.setCity( "Paris" ); primeMinisterEntry.setStreet( "Hotel Matignon" ); primeMinisterEntry.setPerson( primeMinister ); book.getEntries().put( helene, heleneEntry ); book.getEntries().put( primeMinister, primeMinisterEntry ); s.persist( book ); s.flush(); s.clear(); book = (AddressBook) s.get( AddressBook.class, book.getId() ); assertEquals( 2, book.getEntries().size() ); assertEquals( heleneEntry.getCity(), book.getEntries().get( helene ).getCity() ); AddressEntryPk fake = new AddressEntryPk( "Fake", "Fake" ); book.getEntries().put( fake, primeMinisterEntry ); s.flush(); s.clear(); book = (AddressBook) s.get( AddressBook.class, book.getId() ); assertEquals( 2, book.getEntries().size() ); assertNull( book.getEntries().get( fake ) ); s.delete( book ); s.flush(); tx.rollback(); s.close(); } @Test public void testMapKeyToEntity() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); AlphabeticalDirectory m = new AlphabeticalDirectory(); m.setName( "M" ); AlphabeticalDirectory v = new AlphabeticalDirectory(); v.setName( "V" ); s.persist( m ); s.persist( v ); AddressBook book = new AddressBook(); book.setOwner( "Emmanuel" ); AddressEntryPk helene = new AddressEntryPk( "Helene", "Michau" ); AddressEntry heleneEntry = new AddressEntry(); heleneEntry.setBook( book ); heleneEntry.setCity( "Levallois" ); heleneEntry.setStreet( "Louis Blanc" ); heleneEntry.setPerson( helene ); heleneEntry.setDirectory( m ); AddressEntryPk primeMinister = new AddressEntryPk( "Dominique", "Villepin" ); AddressEntry primeMinisterEntry = new AddressEntry(); primeMinisterEntry.setBook( book ); primeMinisterEntry.setCity( "Paris" ); primeMinisterEntry.setStreet( "Hotel Matignon" ); primeMinisterEntry.setPerson( primeMinister ); primeMinisterEntry.setDirectory( v ); book.getEntries().put( helene, heleneEntry ); book.getEntries().put( primeMinister, primeMinisterEntry ); s.persist( book ); s.flush(); s.clear(); book = (AddressBook) s.get( AddressBook.class, book.getId() ); assertEquals( 2, book.getEntries().size() ); assertEquals( heleneEntry.getCity(), book.getEntries().get( helene ).getCity() ); assertEquals( "M", book.getEntries().get( helene ).getDirectory().getName() ); s.delete( book ); tx.rollback(); s.close(); } @Test @RequiresDialect({HSQLDialect.class, H2Dialect.class}) public void testComponentSubPropertyMapKey() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); AddressBook book = new AddressBook(); book.setOwner( "Emmanuel" ); AddressEntryPk helene = new AddressEntryPk( "Helene", "Michau" ); AddressEntry heleneEntry = new AddressEntry(); heleneEntry.setBook( book ); heleneEntry.setCity( "Levallois" ); heleneEntry.setStreet( "Louis Blanc" ); heleneEntry.setPerson( helene ); AddressEntryPk primeMinister = new AddressEntryPk( "Dominique", "Villepin" ); AddressEntry primeMinisterEntry = new AddressEntry(); primeMinisterEntry.setBook( book ); primeMinisterEntry.setCity( "Paris" ); primeMinisterEntry.setStreet( "Hotel Matignon" ); primeMinisterEntry.setPerson( primeMinister ); book.getEntries().put( helene, heleneEntry ); book.getEntries().put( primeMinister, primeMinisterEntry ); s.persist( book ); s.flush(); s.clear(); book = (AddressBook) s.get( AddressBook.class, book.getId() ); assertEquals( 2, book.getLastNameEntries().size() ); assertEquals( heleneEntry.getCity(), book.getLastNameEntries().get( "Michau" ).getCity() ); AddressEntryPk fake = new AddressEntryPk( "Fake", "Fake" ); book.getEntries().put( fake, primeMinisterEntry ); s.flush(); s.clear(); book = (AddressBook) s.get( AddressBook.class, book.getId() ); assertEquals( 2, book.getEntries().size() ); assertNull( book.getEntries().get( fake ) ); s.delete( book ); tx.rollback(); s.close(); } @Test public void testMapKeyOnManyToMany() throws Exception { Session s; s = openSession(); s.getTransaction().begin(); News airplane = new News(); airplane.setTitle( "Crash!" ); airplane.setDetail( "An airplaned crashed." ); s.persist( airplane ); Newspaper lemonde = new Newspaper(); lemonde.setName( "Lemonde" ); lemonde.getNews().put( airplane.getTitle(), airplane ); s.persist( lemonde ); s.flush(); s.clear(); lemonde = (Newspaper) s.get( Newspaper.class, lemonde.getId() ); assertEquals( 1, lemonde.getNews().size() ); News news = lemonde.getNews().get( airplane.getTitle() ); assertNotNull( news ); assertEquals( airplane.getTitle(), news.getTitle() ); s.delete( lemonde ); s.delete( news ); s.getTransaction().rollback(); s.close(); } @Test public void testMapKeyOnManyToManyOnId() throws Exception { Session s; s = openSession(); s.getTransaction().begin(); News hibernate1 = new News(); hibernate1.setTitle( "#1 ORM solution in the Java world" ); hibernate1.setDetail( "Well, that's no news ;-)" ); s.persist( hibernate1 ); PressReleaseAgency schwartz = new PressReleaseAgency(); schwartz.setName( "Schwartz" ); schwartz.getProvidedNews().put( hibernate1.getId(), hibernate1 ); s.persist( schwartz ); s.flush(); s.clear(); schwartz = (PressReleaseAgency) s.get( PressReleaseAgency.class, schwartz.getId() ); assertEquals( 1, schwartz.getProvidedNews().size() ); News news = schwartz.getProvidedNews().get( hibernate1.getId() ); assertNotNull( news ); assertEquals( hibernate1.getTitle(), news.getTitle() ); s.delete( schwartz ); s.delete( news ); s.getTransaction().rollback(); s.close(); } @Test public void testMapKeyAndIdClass() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); Painter picasso = new Painter(); Painting laVie = new Painting( "La Vie", "Picasso", 50, 20 ); picasso.getPaintings().put( "La Vie", laVie ); Painting famille = new Painting( "La Famille du Saltimbanque", "Picasso", 50, 20 ); picasso.getPaintings().put( "La Famille du Saltimbanque", famille ); s.persist( picasso ); s.flush(); s.clear(); picasso = (Painter) s.get( Painter.class, picasso.getId() ); Painting painting = picasso.getPaintings().get( famille.getName() ); assertNotNull( painting ); assertEquals( painting.getName(), famille.getName() ); s.delete( picasso ); tx.rollback(); s.close(); } @Test public void testRealMap() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); Atmosphere atm = new Atmosphere(); Atmosphere atm2 = new Atmosphere(); GasKey key = new GasKey(); key.setName( "O2" ); Gas o2 = new Gas(); o2.name = "oxygen"; atm.gases.put( "100%", o2 ); atm.gasesPerKey.put( key, o2 ); atm2.gases.put( "100%", o2 ); atm2.gasesPerKey.put( key, o2 ); s.persist( key ); s.persist( atm ); s.persist( atm2 ); s.flush(); s.clear(); atm = (Atmosphere) s.get( Atmosphere.class, atm.id ); key = (GasKey) s.get( GasKey.class, key.getName() ); assertEquals( 1, atm.gases.size() ); assertEquals( o2.name, atm.gases.get( "100%" ).name ); assertEquals( o2.name, atm.gasesPerKey.get( key ).name ); tx.rollback(); s.close(); } @Test public void testTemporalKeyMap() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); Atmosphere atm = new Atmosphere(); atm.colorPerDate.put( new Date(1234567000), "red" ); s.persist( atm ); s.flush(); s.clear(); atm = (Atmosphere) s.get( Atmosphere.class, atm.id ); assertEquals( 1, atm.colorPerDate.size() ); final Date date = atm.colorPerDate.keySet().iterator().next(); final long diff = new Date( 1234567000 ).getTime() - date.getTime(); assertTrue( "24h diff max", diff > 0 && diff < 24*60*60*1000 ); tx.rollback(); s.close(); } @Test public void testEnumKeyType() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); Atmosphere atm = new Atmosphere(); atm.colorPerLevel.put( Atmosphere.Level.HIGH, "red" ); s.persist( atm ); s.flush(); s.clear(); atm = (Atmosphere) s.get( Atmosphere.class, atm.id ); assertEquals( 1, atm.colorPerLevel.size() ); assertEquals( "red", atm.colorPerLevel.get(Atmosphere.Level.HIGH) ); tx.rollback(); s.close(); } @Test public void testMapKeyEntityEntity() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); AddressBook book = new AddressBook(); s.persist( book ); AddressEntry entry = new AddressEntry(); entry.setCity( "Atlanta"); AddressEntryPk pk = new AddressEntryPk("Coca", "Cola" ); entry.setPerson( pk ); entry.setBook( book ); AlphabeticalDirectory ad = new AlphabeticalDirectory(); ad.setName( "C"); s.persist( ad ); entry.setDirectory( ad ); s.persist( entry ); book.getDirectoryEntries().put( ad, entry ); s.flush(); s.clear(); book = (AddressBook) s.get( AddressBook.class, book.getId() ); assertEquals( 1, book.getDirectoryEntries().size() ); assertEquals( "C", book.getDirectoryEntries().keySet().iterator().next().getName() ); tx.rollback(); s.close(); } @Test public void testEntityKeyElementTarget() throws Exception { Session s = openSession(); Transaction tx = s.beginTransaction(); Atmosphere atm = new Atmosphere(); Gas o2 = new Gas(); o2.name = "oxygen"; atm.composition.put( o2, 94.3 ); s.persist( o2 ); s.persist( atm ); s.flush(); s.clear(); atm = (Atmosphere) s.get( Atmosphere.class, atm.id ); assertTrue( ! Hibernate.isInitialized( atm.composition ) ); assertEquals( 1, atm.composition.size() ); assertEquals( o2.name, atm.composition.keySet().iterator().next().name ); tx.rollback(); s.close(); } @Test public void testSortedMap() { Session s = openSession(); Transaction tx = s.beginTransaction(); Training training = new Training(); Trainee trainee = new Trainee(); trainee.setName( "Jim" ); Trainee trainee2 = new Trainee(); trainee2.setName( "Emmanuel" ); s.persist( trainee ); s.persist( trainee2 ); training.getTrainees().put( "Jim", trainee ); training.getTrainees().put( "Emmanuel", trainee2 ); s.persist( training ); s.flush(); s.clear(); training = (Training) s.get( Training.class, training.getId() ); assertEquals( "Emmanuel", training.getTrainees().firstKey() ); assertEquals( "Jim", training.getTrainees().lastKey() ); tx.rollback(); s.close(); } @Test public void testMapKeyLoad() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); Software hibernate = new Software(); hibernate.setName( "Hibernate" ); Version v1 = new Version(); v1.setCodeName( "HumbaHumba" ); v1.setNumber( "1.0" ); v1.setSoftware( hibernate ); hibernate.addVersion( v1 ); s.persist( hibernate ); s.persist( v1 ); s.flush(); s.clear(); hibernate = (Software) s.get( Software.class, "Hibernate" ); assertEquals(1, hibernate.getVersions().size() ); Version v2 = new Version(); v2.setCodeName( "HumbaHumba2" ); v2.setNumber( "2.0" ); v2.setSoftware( hibernate ); hibernate.addVersion( v2 ); assertEquals( "One loaded persisted version, and one just added", 2, hibernate.getVersions().size() ); s.flush(); s.clear(); hibernate = (Software) s.get( Software.class, "Hibernate" ); for ( Version v : hibernate.getVersions().values() ) { s.delete( v ); } s.delete( hibernate ); tx.rollback(); s.close(); } @Override protected Class[] getAnnotatedClasses() { return new Class[]{ Wardrobe.class, Drawer.class, Dress.class, Software.class, Version.class, AddressBook.class, AddressEntry.class, AddressEntryPk.class, //should be silently ignored Newspaper.class, News.class, PressReleaseAgency.class, Painter.class, Painting.class, Atmosphere.class, Gas.class, AlphabeticalDirectory.class, GasKey.class, Trainee.class, Training.class }; } }