Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Hibernate Bug Wrong Parameter Binding

I have this simple Hibernate code.

public List<Student>bug(){
    //SimpleCriteria
    final Criterion eq = and(Restrictions.eq("fdl","N"),Restrictions.eq("cid",1),Restrictions.eq("did",2));
    return currentSession().createCriteria(Student.class)                
           .createAlias("school","s",JoinType.INNER_JOIN,Restrictions.eq("zipCode",1764))               
           .createAlias("address","a",JoinType.LEFT_OUTER_JOIN,eq)
           .setProjection(addProjection("id"))
           .setResultTransformer(transformer(Student.class))                
           .list();
}      

The problem is the parameters and somehow disorder or mixed or in a wrong position each one the problem arises when i create two createAlias both with at least a criterion like this(See Update below)

createAlias With Some Criterions

createAlias("school","s",JoinType.INNER_JOIN,Restrictions.eq("zipCode",1764))               
createAlias("address","a",JoinType.LEFT_OUTER_JOIN,eq)

The sql generated seems good..

select
    this_.ID as y0_ 
from
    student this_ 
left outer join
    address address2_ 
        on this_.C05=address2_.ID 
        and (
            (
                address2_.FDL=? 
                and address2_.CID=? 
                and address2_.DID=?
            ) 
        ) 
inner join
    school school_ 
        on this_.C03=school_.ID 
        and (
            school_.C06=? //ZIPCODE
        )

Even when i see the log4j i can see the wrong binding enter image description here

You can see the zip code value 1764 is bind to the first parameter which is address2_.FDL

binding parameter [1] as [INTEGER] - [1764]

Later the second parameter which is cid is assigned the correct previous value for fdl which is 'N'

Message: binding parameter [2] as [VARCHAR] - [N]

Later the third parameter which is did is assigned the correct previous value for cid which is 1

binding parameter [3] as [INTEGER] - [1]

Later the four parameter which is zipCode is assigned the correct previous value for did which is 2

binding parameter [4] as [INTEGER] - [2]

Of course the generatedsql match log4j binding

select
    this_.ID as y0_ 
from
    student this_ 
left outer join
    address address2_ 
        on this_.C05=address2_.ID 
        and (
            (
                address2_.FDL=1764 
                and address2_.CID='N'
                and address2_.DID=1
            ) 
        ) 
inner join
    school school_ 
        on this_.C03=school_.ID 
        and (
            school_.C06=2 //ZIPCODE
        )

As you can see the binding is clearly wrong.

Expected<---------------->Reality

1 parameter fdl should be bind to 'N' but is bind to zipCode value which is 1764
2 parameter cid should be bind to 1 but is bind to fdl value which is 'N'
3 parameter did should be bind to 2 but is bind to cid value which is 1
4 parameter zipCode should be bind to 1764 but is bind to did value which is 2

What i think is happening Hibernate mix the parameters positions for some reason.

I was using Hibernate 4.3.4 when this problem come across but i see a similiar bug which was fixed in 5.2.2 https://hibernate.atlassian.net/browse/HHH-10991 and i upgrade to Hibernate 5.2.2 and the same problem come across i have seen a lot of forum reporting this problem why hibernate doesn't fix it? Of course i have workarounds but this problem is very annoying

If i use the 2 createAlias with not criterion everything works like expected

createAlias("school","s",JoinType.INNER_JOIN,Restrictions.eq("zipCode",1764))               
createAlias("address","a",JoinType.LEFT_OUTER_JOIN)

Environment

Java: 1.8.0_74; Java HotSpot(TM) 64-Bit Server VM 25.74-b02
Hibernate 5.2.2 and 4.3.4 tested in both.
Netbeans NetBeans IDE 8.1 (Build 201510222201)

Another similiar forums

https://forum.hibernate.org/viewtopic.php?f=1&t=947018
https://forum.hibernate.org/viewtopic.php?f=1&t=971534
https://hibernate.atlassian.net/browse/HHH-2496
https://hibernate.atlassian.net/browse/HHH-1743

UPDATE

The parameters goes wrong even when are 2 parameters

public List<Student>bug(){
    return currentSession().createCriteria(Student.class)                
     .createAlias("school","s",JoinType.INNER_JOIN,Restrictions.eq("zipCode",1764))               
     .createAlias("address","a",JoinType.LEFT_OUTER_JOIN,Restrictions.eq("fdl","N"))
     .setProjection(addProjection("id"))
     .setResultTransformer(transformer(Student.class))                
     .list();
}      

As you can see the binding is clearly wrong.

Expected<---------------->Reality

1 parameter fdl should be bind to 'N' but is bind to zipCode value which is 1764
2 parameter zipCode should be bind to 1764 but is bind to fdl value which is 'N'
like image 457
chiperortiz Avatar asked Aug 16 '16 00:08

chiperortiz


1 Answers

... and the same problem come across i have seen a lot of forum reporting this problem why hibernate doesn't fix it?

org.hibernate.Criteria API is considered deprecated:

Hibernate offers an older, legacy org.hibernate.Criteria API which should be considered deprecated. No feature development will target those APIs. Eventually, Hibernate-specific criteria features will be ported as extensions to the JPA javax.persistence.criteria.CriteriaQuery.

Thus you should not expect a lot of effort related to org.hibernate.Criteria API (including bug fixing) in future versions.

I suggest you migrate to JPA CriteriaQuery API. However, I personally don't like it either, and I always use either JPQL/HQL directly or QueryDSL which I find as a very good balance between JPQL string-ness and the high verbosity of CriteriaQuery APIs.

like image 105
Dragan Bozanovic Avatar answered Sep 21 '22 10:09

Dragan Bozanovic