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

ESC (JIRA) noreply at atlassian.com
Wed Dec 5 04:06:56 EST 2007


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-2991?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_29054 ] 

ESC commented on HHH-2991:
--------------------------

Jaime is right with the bug (ie. it exists) but he is wrong with the code (ie. that is not the hibernate code, and in deed that code has no any bug...)

The hibernate code is this:

public static Constructor getConstructor(Class clazz, Type[] types) throws PropertyNotFoundException {
		final Constructor[] candidates = clazz.getConstructors();
		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() );
	}

As you can see they get only the public constructors:
	final Constructor[] candidates = clazz.getConstructors();

They must do it in an homogeneus way, they can't get only public constructors and then ensure the selected contructor is public (obviously it is).

Please fix this bug soon and (improbable) document it ^_^

Kind Regards.

> 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
>
>   Original Estimate: 10 minutes
>  Remaining Estimate: 10 minutes
>
> 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