参数化本机查询返回空结果集[参数为逗号分隔字符串](使用JPA)

时间:2016-09-26 07:36:05

标签: java oracle jpa jpa-2.0 nativequery

我正在尝试使用JPA 2.0执行本机查询。我已在orm.xml中定义了我的本机查询

 Orm.xml
    <named-native-query name="getAgencyUsersByRoles">
        <query><![CDATA[SELECT DISTINCT a1.USR_LOGIN,c.PERSON_FIRST_NAME,c.PERSON_LAST_NAME,a1.EMAIL, b.auth_role_code FROM USERS a1,PERSON_AUTH_ROLES b,PERSON c WHERE ((b.group_code = 'RCATAG' and a1.person_id=b.person_id and b.person_id=c.person_id AND b.auth_role_code IN (?)) OR (b.group_code = 'RCEMP' and a1.person_id=b.person_id and b.person_id=c.person_id AND b.auth_role_code IN (?) ) ) AND a1.email IS NOT NULL AND a1.status in ('ACTIVE','PASSWORD EXPIRED')  ORDER BY a1.usr_login]]></query>
    </named-native-query>

我使用jpa执行查询的代码。

    Query query = getEntityManager()
            .createNamedQuery(NotificationPersistenceConstants.GET_AGENCY_USERS_BY_ROLES);
    query.setParameter(1, roles);
    query.setParameter(2, cccRoles);
    // fetch the results
    List<Object[]> list = query.getResultList();

此查询在执行时不会抛出任何异常我验证了我的appplication的jpa日志但返回了空结果集。

当我在我的数据库服务器中触发相同的查询时,我得到的结果集证明我的查询没有问题,并且表保存了针对此查询返回的记录。

我试图打破我的原生查询,只是将它们作为查询中所有表的单独本机查询执行。 下面是我尝试使用DISTINCT子句来检查DISTINCT关键字是否可能是罪魁祸首。但他们都运作良好,并在List<Object[]>

下给出了结果
SELECT DISTINCT a1.USR_LOGIN FROM USERS a1 ORDER BY a1.usr_login
SELECT DISTINCT b.auth_role_code FROM PERSON_AUTH_ROLES b
SELECT DISTINCT c.PERSON_LAST_NAME FROM PERSON c

更新了角色&amp; cccRoles查询我在查询中传递的参数。

roles = 'teller','lender','bacth',etc... // This list is dynamically created at runtime
cccRoles = 'cccadmin','ccuser',etc // This list is dynamically created at runtime

现在我不确定是什么问题。

查询? - 不应该像我验证的那样直接在DB服务器上运行相同的查询并且运行良好。

EntityManager(JPA)? - 验证了所有配置,并执行了上面提到的各个查询,并得到了结果。

加入?...

如果有人使用WAS 8.5,JPA 2.0遇到同样的问题,请帮助我。

2 个答案:

答案 0 :(得分:1)

好的我能够深入查看我的问题并发现问题与我设置Query对象的参数有关。

罪魁祸首的代码行:

String roles = 'teller','lender','bacth';// This list is dynamically created at runtime of nth elements
Strign cccRoles = 'cccadmin','ccuser';// This list is dynamically created at runtime of nth elements
Query query = getEntityManager().createNamedQuery(NotificationPersistenceConstants.GET_AGENCY_USERS_BY_ROLES);
query.setParameter(1,roles);
query.setParameter(1,cccRoles);

在上面的代码中roles&amp; cccRoles字符串替换单个字符串?我的查询字符串中的占位符,所以当查询被解释为find时,整个字符串(即'teller','lender','bacth')与数据库中每个数据库记录的提及列b.auth_role_code匹配因此它没有找到任何反对它的记录。

然而,如果我通过在查询中直接替换此字符串参数(roles&amp; cccRoles)而在java中构建相同的查询字符串,然后调用createNativeQuery(),它的工作方式如下: / p>

Query query = getEntityManager().createNativeQuery("SELECT DISTINCT a1.USR_LOGIN,c.PERSON_FIRST_NAME,c.PERSON_LAST_NAME,a1.EMAIL, b.auth_role_code FROM USERS a1,PERSON_AUTH_ROLES b,PERSON c WHERE ((b.group_code = 'RCATAG' and a1.person_id=b.person_id and b.person_id=c.person_id AND b.auth_role_code IN ('teller','lender','bacth')) OR (b.group_code = 'RCEMP' and a1.person_id=b.person_id and b.person_id=c.person_id AND b.auth_role_code IN ('cccadmin','ccuser') ) ) AND a1.email IS NOT NULL AND a1.status in ('ACTIVE','PASSWORD EXPIRED')  ORDER BY a1.usr_login");

底线:每当使用?(placeholder)对象中的setParameter在sql查询中发生Query的子位置时,它就会被映射为单个列值,即使传递的参数字符串以逗号分隔。

但是当通过直接连接参数字符串(不使用setParameter)然后执行来在java中构建相同的查询时,它会工作并将其视为要查找的字符串列表。

此类情况的可能解决方案:

  • 替换并构建连接所有此类动态字符串参数列表的完整查询。(不使用setParameter())ans使用createNativeQuery()执行
  • 使用JPA提供程序的Criteria Builder API并构建查询,然后执行。 (推荐)
  • 构建必需的号码。 ?(placeholders)基于List的大小,然后调用等价的no。循环中的setParameters。

  • ?? (任何人都有其他更好的解决方案来帮助这种情况。)

虽然我仍然试图回答一下在java中运行时构建相同查询字符串与使用query.setParameter()设置查询参数时调用createNativeQuery vs之间的区别。

答案 1 :(得分:0)

这可能是因为您在单个参数中传递了连接的参数'teller','lender','bacth',因此它在jpa中作为单个字符串参数进行比较。 因此它没有返回任何结果。