[hibernate-issues] [Hibernate-JIRA] Created: (HHH-2991) Non public constructors cannot be used whith 'select new Object(...)' in HQL

Jaime Porras (JIRA) noreply at atlassian.com
Tue Dec 4 07:30:56 EST 2007


Non public constructors cannot be used whith 'select new Object(...)' in HQL
----------------------------------------------------------------------------

                 Key: HHH-2991
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2991
             Project: Hibernate3
          Issue Type: Bug
          Components: query-hql
    Affects Versions: 3.2.5
         Environment: Hibernate 3.2.5
            Reporter: Jaime Porras
            Priority: Minor
         Attachments: ReflectHelper.java

Using following HQL

<query name="family">
<![CDATA[
select new Family(mother, mate, offspr)
from DomesticCat as mother
   join mother.mate as mate
   left join mother.kittens as offspr
]]>
</query>

with

public class Family {

   protected Family(String mother, String mate, String offspr) {
       // code
   }
}

Note: assuming Family constructor is correct (argument types are correct)


During hql analyzing process, Hibernate produces the following error:

SEVERE: Error in named query: family
org.hibernate.hql.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [Family] [
select new Family(mother, mate, offspr)
from DomesticCat as mother
   join mother.mate as mate
   left join mother.kittens as offspr
]

This error is produced because Family constructor is protected (may be private). 

org.hibernate.util.ReflectHelper is the class used to find the appropriate constructor. But the code used to do it calls clazz.getConstructors(), getting only the public contructors:

public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
		final Constructor[] candidates = clazz.getDeclaredConstructors(); // Get all constructors (public and not public)
		for ( int i=0; i<candidates.length; i++ ) {
			final Constructor constructor = candidates[i];
			final Class[] params = constructor.getParameterTypes();
			if ( params.length==types.length ) {
				boolean found = true;
				for ( int j=0; j<params.length; j++ ) {
					final boolean ok = params[j].isAssignableFrom( types[j].getReturnedClass() ) || (
						types[j] instanceof PrimitiveType &&
						params[j] == ( (PrimitiveType) types[j] ).getPrimitiveClass()
					);
					if (!ok) {
						found = false;
						break;
					}
				}
				if (found) {
					if ( !isPublic(clazz, constructor) ) constructor.setAccessible(true);
					return constructor;
				}
			}
		}
		throw new PropertyNotFoundException( "no appropriate constructor in class: " + clazz.getName() );
}

The only thing to do is change the first line by:

final Constructor[] candidates = clazz.getDeclaredConstructors();

PD:
If only public constructors will be used the this code has no sense:
	if (found) {
		if ( !isPublic(clazz, constructor) ) constructor.setAccessible(true);
		return constructor;
	}


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list