diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java index 24c0600ec2..f994f6b3ce 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java @@ -79,6 +79,7 @@ public abstract class AbstractPathImpl /** * {@inheritDoc} */ + @Override public PathSource getParentPath() { return getPathSource(); } @@ -94,6 +95,7 @@ public abstract class AbstractPathImpl /** * {@inheritDoc} */ + @Override public String getPathIdentifier() { return getPathSource().getPathIdentifier() + "." + getAttribute().getName(); } @@ -135,6 +137,7 @@ public abstract class AbstractPathImpl * {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) + @Override public Path get(SingularAttribute attribute) { if ( ! canBeDereferenced() ) { throw illegalDereference(); @@ -152,6 +155,7 @@ public abstract class AbstractPathImpl * {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) + @Override public > Expression get(PluralAttribute attribute) { if ( ! canBeDereferenced() ) { throw illegalDereference(); @@ -169,6 +173,7 @@ public abstract class AbstractPathImpl * {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) + @Override public > Expression get(MapAttribute attribute) { if ( ! canBeDereferenced() ) { throw illegalDereference(); @@ -186,6 +191,7 @@ public abstract class AbstractPathImpl * {@inheritDoc} */ @SuppressWarnings({ "unchecked" }) + @Override public Path get(String attributeName) { if ( ! canBeDereferenced() ) { throw illegalDereference(); @@ -241,10 +247,11 @@ public abstract class AbstractPathImpl /** * {@inheritDoc} */ + @Override public void registerParameters(ParameterRegistry registry) { // none to register } - + @Override public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { // Make sure we delegate up to our source (eventually up to the path root) to // prepare the path properly. @@ -257,6 +264,7 @@ public abstract class AbstractPathImpl /** * {@inheritDoc} */ + @Override public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { PathSource source = getPathSource(); if ( source != null ) { @@ -270,6 +278,7 @@ public abstract class AbstractPathImpl /** * {@inheritDoc} */ + @Override public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { return render( renderingContext ); } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java index fb7c1e097c..910521d0f5 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java @@ -37,8 +37,10 @@ import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.Type; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.MapJoinImplementor; import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.PathSource; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.persister.collection.CollectionPersister; @@ -74,7 +76,7 @@ public class MapKeyHelpers { public MapKeySource getPathSource() { return (MapKeySource) super.getPathSource(); } - + @Override public MapKeyAttribute getAttribute() { return mapKeyAttribute; } @@ -89,6 +91,20 @@ public class MapKeyHelpers { return ! isBasicTypeKey(); } + @Override + public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + PathSource source = getPathSource(); + String name; + if ( source != null ) { + source.prepareAlias( renderingContext ); + name = source.getPathIdentifier(); + } + else { + name = getAttribute().getName(); + } + return "key(" + name + ")"; + } + @Override protected Attribute locateAttributeInternal(String attributeName) { if ( ! canBeDereferenced() ) { @@ -98,7 +114,7 @@ public class MapKeyHelpers { } throw new UnsupportedOperationException( "Not yet supported!" ); } - + @Override public Bindable getModel() { return mapKeyAttribute; } @@ -127,12 +143,13 @@ public class MapKeyHelpers { this.mapJoin = mapJoin; this.mapAttribute = attribute; } - + @Override public MapAttribute getAttribute() { return mapAttribute; } @SuppressWarnings({ "unchecked" }) + @Override public Bindable> getModel() { // TODO : ok??? the attribute is in fact bindable, but its type signature is different return (Bindable>) mapAttribute; @@ -143,6 +160,11 @@ public class MapKeyHelpers { return (PathImplementor) mapJoin.getParentPath(); } + @Override + public String getPathIdentifier() { + return mapJoin.getPathIdentifier(); + } + @Override protected boolean canBeDereferenced() { return false; @@ -186,8 +208,7 @@ public class MapKeyHelpers { : BindableType.SINGULAR_ATTRIBUTE; String guessedRoleName = determineRole( attribute ); - SessionFactoryImplementor sfi = (SessionFactoryImplementor) - criteriaBuilder.getEntityManagerFactory().getSessionFactory(); + SessionFactoryImplementor sfi = criteriaBuilder.getEntityManagerFactory().getSessionFactory(); mapPersister = sfi.getCollectionPersister( guessedRoleName ); if ( mapPersister == null ) { throw new IllegalStateException( "Could not locate collection persister [" + guessedRoleName + "]" ); @@ -212,6 +233,7 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public String getName() { // TODO : ??? return "map-key"; @@ -220,6 +242,7 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public PersistentAttributeType getPersistentAttributeType() { return persistentAttributeType; } @@ -227,6 +250,7 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public ManagedType> getDeclaringType() { // TODO : ??? return null; @@ -235,6 +259,7 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public Class getJavaType() { return attribute.getKeyJavaType(); } @@ -242,6 +267,7 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public Member getJavaMember() { // TODO : ??? return null; @@ -250,6 +276,7 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public boolean isAssociation() { return mapKeyType.isEntityType(); } @@ -257,30 +284,31 @@ public class MapKeyHelpers { /** * {@inheritDoc} */ + @Override public boolean isCollection() { return false; } - + @Override public boolean isId() { return false; } - + @Override public boolean isVersion() { return false; } - + @Override public boolean isOptional() { return false; } - + @Override public Type getType() { return jpaType; } - + @Override public BindableType getBindableType() { return jpaBindableType; } - + @Override public Class getBindableJavaType() { return jpaBinableJavaType; } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/basic/MapKeyTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/basic/MapKeyTest.java new file mode 100644 index 0000000000..dc302bdca8 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/criteria/basic/MapKeyTest.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, 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.ejb.criteria.basic; + +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.MapJoin; +import javax.persistence.criteria.Root; + +import org.hibernate.ejb.metamodel.Employee; +import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.TestForIssue; + +import org.junit.Test; + +public class MapKeyTest extends BaseEntityManagerFunctionalTestCase { + + @Test + @TestForIssue(jiraKey = "HHH-6103") + public void testCastToString() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder builder = em.getCriteriaBuilder(); + CriteriaQuery criteria = builder.createQuery( Employee.class ); + Root employeeRoot = criteria.from( Employee.class ); + criteria.select( employeeRoot ); + MapJoin phoneRoot = employeeRoot.joinMap( "phoneNumbers" ); + criteria.where( builder.equal( phoneRoot.key(), "HOME" ) ); + em.createQuery( criteria ).getResultList(); + + em.getTransaction().commit(); + em.close(); + } + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { + Employee.class + }; + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/metamodel/Employee.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/metamodel/Employee.java new file mode 100644 index 0000000000..7e965385ec --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/metamodel/Employee.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, 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.ejb.metamodel; + +import java.util.Map; +import javax.persistence.*; + +@Entity +public class Employee implements java.io.Serializable { + + @Id + private Long id; + + @ElementCollection(fetch=FetchType.LAZY) + @CollectionTable(name="emp_phone") + @MapKeyColumn(name="phone_type") + @Column(name="phone_num") + private Map phoneNumbers; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Map getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(Map phoneNumbers) { + this.phoneNumbers = phoneNumbers; + } +} \ No newline at end of file