spring data jpa dao层接口返回元素为null的list

项目使用Spring Data JPA作为数据层的框架,用来操作数据库。
其支持使用 @Query 注解来自定义查询语句,正是此功能,遇到了一个问题,返回的结果集包含了null的元素

项目中有 用户表、角色表、用户关联角色表,想要实现通过角色ID查询所有相关联用户信息。
代码如下,大家可以先思考下异同:

public interface UserToRoleDao extends JpaRepositoryImplementation<UserToRolePO, String> {

	@Query("select u from UserToRolePO utr left join UserPO u on utr.userId = u.id and utr.roleId = ?1")
	List<UserPO> findUsersByRoleId(String roleId);

	@Query("select u from UserToRolePO utr left join UserPO u on utr.userId = u.id where utr.roleId = ?1")
	List<UserPO> findUsersByRoleId2(String roleId);

}

有区别吗?
是的,sql的左后一段,判断roleId用了不同的方式。
findUsersByRoleId 方法使用了 and,findUsersByRoleId2方法使用了 where。

最终的结果就是,当查询的角色并没有关联任何一个用户时,findUsersByRoleId 返回了拥有1个元素的list,但是这一个元素是null;findUsersByRoleId2 返回了一个空的list。

探究下所以然,开启了jpa的show_sql = true。当执行查询时打印日志。在控制台看到两个查询对应的sql语句。

@Query("select u from UserToRolePO utr left join UserPO u on utr.userId = u.id and utr.roleId = ?1")
List<UserPO> findUsersByRoleId(String roleId);
对应的sql,记为sql1:
SELECT
	userpo1_.id AS id1_13_,
	userpo1_.name AS name10_13_,
	userpo1_.nickname AS nicknam11_13_,
	userpo1_.password AS passwor12_13_
FROM
	role_to_user roletou0_
LEFT OUTER JOIN sys_user userpo1_ ON (
	roletou0_.user_id = userpo1_.id
	AND roletou0_.role_id = '?'
)
///
///
@Query("select u from UserToRolePO utr left join UserPO u on utr.userId = u.id where utr.roleId = ?1")
List<UserPO> findUsersByRoleId2(String roleId);
对应的sql是,记为sql2:
SELECT
	userpo1_.id AS id1_13_,
	userpo1_.name AS name10_13_,
	userpo1_.nickname AS nicknam11_13_,
	userpo1_.password AS passwor12_13_
FROM
	role_to_user roletou0_
LEFT OUTER JOIN sys_user userpo1_ ON (
	roletou0_.user_id = userpo1_.id
)
WHERE
	roletou0_.role_id = '?'
}

随便填个role_id,拿这两条sql语句分别在数据库中执行,果然,返回结果是不一样的。(如果是在图形化工具上执行sql,可能看到结果是一样的。为了避免图形化工具瞎掺和的情况,博主特意在shell窗口执行sql。)
开启shell终端,执行 mysql -uroot -proot 登录mysql,执行 use test_db; 切换到指定数据库。
分别执行上述sql语句,可以看到,
sql1 返回了一行全是null值的记录。
在这里插入图片描述
sql2返回了 “Empty set”
在这里插入图片描述

这就可以初略解释为什么两种写法在程序中的结果不一致。至于msyql是如何解析执行sql的,等有时间再研究吧。


end

JPA是Java Persistence API的缩写,是Java EE规范中用于ORM(对象关系映射)的API。它定义了一组接口和注解,使开发人员可以通过编写面向对象的代码来操作数据库。引用提到了在pom.xml中添加了两个依赖,即org.springframework.data:spring-data-jpa和org.springframework.boot:spring-boot-starter-data-jpa,这是使用Spring Data JPA时需要添加的依赖。 Spring Data JPA是在JPA规范下对Repository进行封装的实现。它提供了一套简化的方法和规范,使开发人员可以更轻松地进行数据库操作。引用中的代码片段展示了如何定义一个符合Spring Data JPA规范的DAO接口。通过继承JpaRepository和JpaSpecificationExecutor接口,我们可以获得封装了基本CRUD操作和复杂查询的功能。 关于JPASpring Data JPA的区别,引用提到了一个很好的解释。JPA是一种规范,而Spring Data JPA是在JPA规范下提供的Repository的实现。通过使用Spring Data JPA,我们可以方便地在不同的ORM框架之间进行切换,而不需要更改代码。Spring Data JPA还对Repository进行了封装,省去了开发人员的不少麻烦。 综上所述,JPA是Java EE规范中的API,而Spring Data JPA是在JPA规范下的Repository的实现。Spring Data JPA封装了JPA规范,提供了更方便的方法和规范,使开发人员可以更轻松地进行数据库操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [JPASpring-Data-JPA简介](https://blog.csdn.net/benjaminlee1/article/details/53087351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [JPA & Spring Data JPA详解](https://blog.csdn.net/cd546566850/article/details/107180272)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值