]
Gail Badner commented on HHH-2991:
----------------------------------
Please attach a runnable test case (Java + mapping) that reproduce this issue.
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: