我正在尝试使用 JPA 2.0 执行 native 查询。我已在 orm.xml 中定义了我的 native 查询
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>
来 self 使用 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();
此查询在执行时不会引发任何异常,我验证了应用程序的 jpa 日志,但返回了空结果集。
当我在数据库服务器中触发相同的查询时,我得到的结果集证明我的查询没有问题,并且表还保存针对此查询返回的记录。
我尝试破坏我的 native 查询,并简单地将它们作为查询中所有表的单独 native 查询执行。
下面是我尝试使用 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
更新了我在查询中传递的角色和 cccRoles 查询参数。
roles = 'teller','lender','bacth',etc... // This list is dynamically created at runtime
cccRoles = 'cccadmin','ccuser',etc // This list is dynamically created at runtime
现在我不确定问题是什么。
查询? - 不应该,因为我验证了直接在数据库服务器中运行相同的查询并且工作良好。
实体管理器(JPA)? - 验证所有配置并执行上述单个查询并返回结果。
加入?...
如果有人在使用 WAS 8.5、JPA 2.0 时遇到同样的问题,请帮助我。
最佳答案
好吧,我能够深入研究我的问题,发现问题出在我设置查询对象的参数上。
罪魁祸首代码行:
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
和 cccRoles
字符串被替换为单个 ?我的查询字符串中存在占位符,因此当查询被解释为查找时,整个字符串(即“teller”、“lender”、“bacth”)与提到的列 b.auth_role_code
与每个字符串进行匹配db 记录在数据库中,因此没有找到任何针对它的记录。
然而,如果我通过直接替换查询中的这个字符串参数(roles
& cccRoles
)来在java中构建相同的查询字符串,然后调用createNativeQuery()它工作原理类似于:
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");
底线:每当在Query
中使用setParameter
在sql查询中发生?(placeholder)
的替换时对象,即使传递的参数字符串是逗号分隔的,它也会映射为单个列值。
但是,当通过直接连接参数字符串(不使用 setParameter)在 java 中构建相同的查询然后执行时,它会工作并将其视为要查找的字符串列表。
此类情况的可能解决方案:
- 替换并构建连接所有此类动态字符串参数列表的完整查询。(不使用
setParameter()
)并使用createNativeQuery()
执行 - 使用 JPA 提供商的 Criteria Builder API 构建查询,然后执行。 (推荐)
构建所需编号。
?(placeholders)
根据列表的大小,然后调用等效的编号。循环中的setParameters。?? (任何人有任何其他更好的解决方案来解决这种情况请帮助。)
虽然我仍然试图得到一个答案,即在 java 中运行时构建相同的查询字符串和调用 createNativeQuery 与使用 query.setParameter() 设置查询参数时有什么区别。
关于java - 参数化 native 查询返回空结果集 [参数为逗号分隔字符串](使用 JPA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39697109/