[ 
https://issues.apache.org/jira/browse/OPENJPA-2788?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Michael Wiles updated OPENJPA-2788:
-----------------------------------
    Description: 
Something that is almost certainly introduced via fixes for OPENJPA-2785 and 
OPENJPA-2733 is that anonymous parameters are not picked up.

The following piece of code does not add the second parameter successfully and 
thus the test fails.

With a Member entity that has a place and a name field:
{code:java}
       Member m = new Member(1, "dave");
        m.setAge(5);
        m.setPlace("capetown");
        em.persist(m);

        CriteriaBuilder cb = em.getCriteriaBuilder();

        CriteriaQuery<Member> q = cb.createQuery(Member.class);
        Root<Member> c = q.from(Member.class);
        ParameterExpression<String> name = cb.parameter(String.class);
        ParameterExpression<String> place = cb.parameter(String.class);
        CriteriaQuery<Member> where = q.select(c).where(cb.equal(c.get("name"), 
name), cb.equal(c.get("place"), place));

        TypedQuery<Member> query = em.createQuery(where);
        query.setParameter(name, "dave");
        query.setParameter(place, "capetown");
        List<Member> results = query.getResultList();

        assertThat(results).isNotEmpty();
{code}
With query and parameter logging on you that the the sql call is made with the 
same parameter twice...
{noformat}
<t 346847161, conn 1824423245> executing prepstmnt 2078396010 SELECT t0.id, 
t0.age, t0.name, t0.place FROM Member t0 WHERE (t0.name = ? AND t0.place = ?) 
[params=(String) dave, (String) dave]
{noformat}
And this kinda makes sense as this is what the 
CriteriaQueryImpl.registerParameter looks like:
{code:java}
    /**
     * Registers the given parameter.
     */
    void registerParameter(ParameterExpressionImpl<?> p) {
        for (Object k : _params.keySet()) {
            if (p.paramEquals(k)) {
                // If a named ParameterExpressin did already get registered
                // with that exact name, then we do ignore it.
                // If we do a query.setParameter("someParamName", Bla)
                // then it must uniquely identify a Parameter.
                return;
            }
        }

        p.setIndex(_params.size());
        _params.put(p, p.getJavaType());
    }
{code}
And 
[paramEquals|https://github.com/apache/openjpa/blob/9f26ed29bf31b5c8ab68c5257d42e8c88765cf9b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java#L142]
 will not differentiate between two anonymous parameters.

So I suspect we are going to need some mechanism for differentiating between 
two anonymous parameters - and if we did this then I suspect the issue that 
caused this in the first place might also be resolved. Possibly add some kind 
of counter or something that can give identity to anonymous parameters.

 Added test to [https://github.com/michaelwiles/openjpa-bugs]

  was:
Something that is almost certainly introduced via fixes for OPENJPA-2785 and 
OPENJPA-2733 is that anonymous parameters are not picked up.

The following piece of code does not add the second parameter successfully and 
thus the test fails.

With a Member entity that has a place and a name field:
{code:java}
       Member m = new Member(1, "dave");
        m.setAge(5);
        m.setPlace("capetown");
        em.persist(m);

        CriteriaBuilder cb = em.getCriteriaBuilder();

        CriteriaQuery<Member> q = cb.createQuery(Member.class);
        Root<Member> c = q.from(Member.class);
        ParameterExpression<String> name = cb.parameter(String.class);
        ParameterExpression<String> place = cb.parameter(String.class);
        CriteriaQuery<Member> where = q.select(c).where(cb.equal(c.get("name"), 
name), cb.equal(c.get("place"), place));

        TypedQuery<Member> query = em.createQuery(where);
        query.setParameter(name, "dave");
        query.setParameter(place, "capetown");
        List<Member> results = query.getResultList();

        assertThat(results).isNotEmpty();
{code}
With query and parameter logging on you that the the sql call is made with the 
same parameter twice...
{noformat}
<t 346847161, conn 1824423245> executing prepstmnt 2078396010 SELECT t0.id, 
t0.age, t0.name, t0.place FROM Member t0 WHERE (t0.name = ? AND t0.place = ?) 
[params=(String) dave, (String) dave]
{noformat}
And this kinda makes sense as this is what the 
CriteriaQueryImpl.registerParameter looks like:
{code:java}
    /**
     * Registers the given parameter.
     */
    void registerParameter(ParameterExpressionImpl<?> p) {
        for (Object k : _params.keySet()) {
            if (p.paramEquals(k)) {
                // If a named ParameterExpressin did already get registered
                // with that exact name, then we do ignore it.
                // If we do a query.setParameter("someParamName", Bla)
                // then it must uniquely identify a Parameter.
                return;
            }
        }

        p.setIndex(_params.size());
        _params.put(p, p.getJavaType());
    }
{code}
And 
[paramEquals|https://github.com/apache/openjpa/blob/9f26ed29bf31b5c8ab68c5257d42e8c88765cf9b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java#L142]
 will not differentiate between two anonymous parameters.

So I suspect we are going to need some mechanism for differentiating between 
two anonymous parameters - and if we did this then I suspect the issue that 
caused this in the first place might also be resolved. Possibly add some kind 
of counter or something that can give identity to anonymous parameters.

 


> Anonymous parameters are not being picked when adding via CriteriaBuilder
> -------------------------------------------------------------------------
>
>                 Key: OPENJPA-2788
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-2788
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: criteria
>    Affects Versions: 3.1.0
>            Reporter: Michael Wiles
>            Priority: Major
>
> Something that is almost certainly introduced via fixes for OPENJPA-2785 and 
> OPENJPA-2733 is that anonymous parameters are not picked up.
> The following piece of code does not add the second parameter successfully 
> and thus the test fails.
> With a Member entity that has a place and a name field:
> {code:java}
>        Member m = new Member(1, "dave");
>         m.setAge(5);
>         m.setPlace("capetown");
>         em.persist(m);
>         CriteriaBuilder cb = em.getCriteriaBuilder();
>         CriteriaQuery<Member> q = cb.createQuery(Member.class);
>         Root<Member> c = q.from(Member.class);
>         ParameterExpression<String> name = cb.parameter(String.class);
>         ParameterExpression<String> place = cb.parameter(String.class);
>         CriteriaQuery<Member> where = 
> q.select(c).where(cb.equal(c.get("name"), name), cb.equal(c.get("place"), 
> place));
>         TypedQuery<Member> query = em.createQuery(where);
>         query.setParameter(name, "dave");
>         query.setParameter(place, "capetown");
>         List<Member> results = query.getResultList();
>         assertThat(results).isNotEmpty();
> {code}
> With query and parameter logging on you that the the sql call is made with 
> the same parameter twice...
> {noformat}
> <t 346847161, conn 1824423245> executing prepstmnt 2078396010 SELECT t0.id, 
> t0.age, t0.name, t0.place FROM Member t0 WHERE (t0.name = ? AND t0.place = ?) 
> [params=(String) dave, (String) dave]
> {noformat}
> And this kinda makes sense as this is what the 
> CriteriaQueryImpl.registerParameter looks like:
> {code:java}
>     /**
>      * Registers the given parameter.
>      */
>     void registerParameter(ParameterExpressionImpl<?> p) {
>         for (Object k : _params.keySet()) {
>             if (p.paramEquals(k)) {
>                 // If a named ParameterExpressin did already get registered
>                 // with that exact name, then we do ignore it.
>                 // If we do a query.setParameter("someParamName", Bla)
>                 // then it must uniquely identify a Parameter.
>                 return;
>             }
>         }
>         p.setIndex(_params.size());
>         _params.put(p, p.getJavaType());
>     }
> {code}
> And 
> [paramEquals|https://github.com/apache/openjpa/blob/9f26ed29bf31b5c8ab68c5257d42e8c88765cf9b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java#L142]
>  will not differentiate between two anonymous parameters.
> So I suspect we are going to need some mechanism for differentiating between 
> two anonymous parameters - and if we did this then I suspect the issue that 
> caused this in the first place might also be resolved. Possibly add some kind 
> of counter or something that can give identity to anonymous parameters.
>  Added test to [https://github.com/michaelwiles/openjpa-bugs]



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to