/*
* 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.hql;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals;
/**
* Test originally written to help verify/diagnose HHH-10125
*
* @author Steve Ebersole
*/
public class MapFunctionExpressionsTest extends BaseNonConfigCoreFunctionalTestCase {
private final ASTQueryTranslatorFactory queryTranslatorFactory = new ASTQueryTranslatorFactory();
@Before
public void prepareTestData() {
Session s = openSession();
s.getTransaction().begin();
AddressType homeType = new AddressType( 1, "home" );
s.persist( homeType );
Address address = new Address( 1, "Main St.", "Somewhere, USA" );
s.persist( address );
Contact contact = new Contact( 1, "John" );
contact.addresses.put( homeType, address );
s.persist( contact );
s.getTransaction().commit();
s.close();
}
@After
public void cleanUpTestData() {
Session s = openSession();
s.getTransaction().begin();
s.delete( s.get( Contact.class, 1 ) );
s.delete( s.get( Address.class, 1 ) );
s.delete( s.get( AddressType.class, 1 ) );
s.getTransaction().commit();
s.close();
}
@Test
public void testMapKeyExpressionInWhere() {
// NOTE : JPA requires that an alias be used in the key() expression. Hibernate allows
// path or alias.
Session s = openSession();
s.getTransaction().begin();
// JPA form
List contacts = s.createQuery( "select c from Contact c join c.addresses a where key(a) is not null" ).list();
assertEquals( 1, contacts.size() );
Contact contact = assertTyping( Contact.class, contacts.get( 0 ) );
// Hibernate additional form
contacts = s.createQuery( "select c from Contact c where key(c.addresses) is not null" ).list();
assertEquals( 1, contacts.size() );
contact = assertTyping( Contact.class, contacts.get( 0 ) );
s.getTransaction().commit();
s.close();
}
@Test
public void testMapKeyExpressionInSelect() {
// NOTE : JPA requires that an alias be used in the key() expression. Hibernate allows
// path or alias.
Session s = openSession();
s.getTransaction().begin();
// JPA form
List types = s.createQuery( "select key(a) from Contact c join c.addresses a" ).list();
assertEquals( 1, types.size() );
assertTyping( AddressType.class, types.get( 0 ) );
// Hibernate additional form
types = s.createQuery( "select key(c.addresses) from Contact c" ).list();
assertEquals( 1, types.size() );
assertTyping( AddressType.class, types.get( 0 ) );
s.getTransaction().commit();
s.close();
}
@Test
public void testMapValueExpressionInSelect() {
Session s = openSession();
s.getTransaction().begin();
List addresses = s.createQuery( "select value(a) from Contact c join c.addresses a" ).list();
assertEquals( 1, addresses.size() );
assertTyping( Address.class, addresses.get( 0 ) );
addresses = s.createQuery( "select value(c.addresses) from Contact c" ).list();
assertEquals( 1, addresses.size() );
assertTyping( Address.class, addresses.get( 0 ) );
s.getTransaction().commit();
s.close();
}
@Test
public void testMapEntryExpressionInSelect() {
Session s = openSession();
s.getTransaction().begin();
List addresses = s.createQuery( "select entry(a) from Contact c join c.addresses a" ).list();
assertEquals( 1, addresses.size() );
assertTyping( Map.Entry.class, addresses.get( 0 ) );
addresses = s.createQuery( "select entry(c.addresses) from Contact c" ).list();
assertEquals( 1, addresses.size() );
assertTyping( Map.Entry.class, addresses.get( 0 ) );
s.getTransaction().commit();
s.close();
}
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] { Address.class, AddressType.class, Contact.class };
}
@Entity(name = "AddressType")
@Table(name = "address_type")
public static class AddressType {
@Id
public Integer id;
String name;
public AddressType() {
}
public AddressType(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "Address")
@Table(name = "address")
// @Embeddable
public static class Address {
@Id
public Integer id;
String street;
String city;
public Address() {
}
public Address(Integer id, String street, String city) {
this.id = id;
this.street = street;
this.city = city;
}
}
@Entity(name = "Contact")
@Table(name = "contact")
public static class Contact {
@Id
public Integer id;
String name;
@OneToMany
@JoinTable(name = "contact_address")
@MapKeyJoinColumn(name="address_type_id", referencedColumnName="id")
// @JoinColumn
// @ElementCollection
// @MapKeyEnumerated(EnumType.STRING)
// @MapKeyColumn(name = "addr_type")
Map<AddressType, Address> addresses = new HashMap<AddressType, Address>();
public Contact() {
}
public Contact(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}