CF Hibernate only accepts arrays for IN ( x ) with named parameters, not positional parameters

StackOverflow https://stackoverflow.com/questions/21830482

  •  12-10-2022
  •  | 
  •  

Question

This sample code demonstrates the issue:

var Names = ['Jon','Anna'];

var Params.Pos1   = [ Names[1] ];
var Params.Pos2   = [ Names[1] , Names[2] ];
var Params.Pos3   = [ Names ];
var Params.Named1 = { name:Names[1] };
var Params.Named2 = { name1:Names[1] , name2:Names[2] };
var Params.Named3 = { names:Names };

var BaseHql = "SELECT COUNT(*) FROM Person WHERE ";
var Queries.Pos1   = BaseHql & "FirstName IN (?)";
var Queries.Pos2   = BaseHql & "FirstName IN (?,?)";
var Queries.Pos3   = BaseHql & "FirstName IN (?)";
var Queries.Named1 = BaseHql & "FirstName IN (:name)";
var Queries.Named2 = BaseHql & "FirstName IN (:name1,:name2)";
var Queries.Named3 = BaseHql & "FirstName IN (:names)";

var Results = {};

for ( var Item in Queries )
{
    try
    {
        Results[Item] = OrmExecuteQuery( Queries[Item] , Params[Item] );
    }
    catch (any cfcatch)
    {
        Results[Item] = "[#cfcatch.message#|#cfcatch.detail#]";
    }
}

Five of the six scenarios there work.

The Queries.Pos3 does not work, despite being exactly equivalent to Queries.Named3 one.

It returns this error message and detail:

Complex object types cannot be converted to simple values.

The expression has requested a variable or an intermediate expression result as a simple value. However, the result cannot be converted to a simple value. Simple values are strings, numbers, boolean values, and date/time values. Queries, arrays, and COM objects are examples of complex values.

The most likely cause of the error is that you tried to use a complex value as a simple one. For example, you tried to use a query variable in a cfif tag.

The stack trace is:

coldfusion.runtime.CfJspPage$ComplexObjectException: Complex object types cannot be converted to simple values.
    at coldfusion.runtime.Cast._String(Cast.java:1036)
    at coldfusion.runtime.Cast._cast(Cast.java:192)
    at coldfusion.orm.ORMUtils.getTypedValue(ORMUtils.java:359)
    at coldfusion.orm.hibernate.HibernatePersistenceManager.setQueryParams(HibernatePersistenceManager.java:844)
    at coldfusion.orm.hibernate.HibernatePersistenceManager._executeHQL(HibernatePersistenceManager.java:781)
    at coldfusion.orm.hibernate.HibernatePersistenceManager.executeHQL(HibernatePersistenceManager.java:753)
    at coldfusion.orm.hibernate.HibernatePersistenceManager.executeQuery(HibernatePersistenceManager.java:615)
    at coldfusion.orm.ORMUtils._executeQuery(ORMUtils.java:344)
    at coldfusion.orm.ORMUtils._executeQuery(ORMUtils.java:311)
    at coldfusion.orm.ORMUtils.executeQuery(ORMUtils.java:303)
    at coldfusion.runtime.CFPage.ORMExecuteQuery(CFPage.java:8933)

Is there something wrong with the code above, or is this a bug/restriction of either CF or Hibernate?

Was it helpful?

Solution

Hibernate seems to use setParameterList to set an array as a single parameter.

The relevant javadoc page shows four versions of setParameterList, but they all accept only named parameters - unlike the setParameter method which has versions with arguments for both name or position.

Thus it appears to be an arbitrary restriction of Hibernate that you cannot pass an array as a positional parameter.

i.e. this code cannot work:

OrmExecuteQuery( "FROM Person WHERE FirstName IN (?)" , [ArrayOfNames] );

The query needs to switched to named parameters, or the positional parameters need to be flattened (e.g. perhaps using ?#RepeatString(',?',ArrayLen()-1)# or similar.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top