java - Mybatis 数据库多表关联分页的问题
问题描述
举个例子:有两个实体类 User 和 Address
public class User { private int id; private String username; // 用户名 private List<Address> addresses; // getter setter...}public class Address { private int id; private String detail; // 详细地址 private User user; //所属用户 // getter setter...}
数据库:
create table t_user( id int(10) primary key auto_increment, username varchar(50));create table t_address( id int(10) primary key auto_increment, detail varchar(255), user_id int(10), CONSTRAINT FOREIGN KEY (user_id) REFERENCES t_user(id));
mybatis映射配置:
<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE mapper PUBLIC '-//mybatis.org//DTD Mapper 3.0//EN' 'http://mybatis.org/dtd/mybatis-3-mapper.dtd'><mapper namespace='org.mkh.shop.model.User'> <resultMap type='User' autoMapping='true'><id property='id' column='u_id'/><collection property='address' ofType='Address'> <id property='id' column='a_id'/> <result property='detail' column='detail'/></collection> </resultMap> <select resultType='User' parameterType='map'>select *,ta.id as ’a_id’,tu.id as ’u_id’ from t_user tu left join t_address ta on ta.user_id=tu.id <where> <if test='name != null'>(username like #{name}) </if></where><if test='sort != null'> order by ${sort} <choose><when test='order != null'>${order}</when><otherwise>asc</otherwise> </choose> </if>limit #{pageOffset},#{pageSize} </select><select resultType='int' parameterType='map'>select count(*) from t_user tu left join t_address ta on ta.user_id=tu.id <where> <if test='name != null'>(username like #{name}) </if></where> </select> </mapper>
用户和地址的关系为:一个用户有多个地址,一个地址只能属于一个用户,一对多假设现在的需求是,分页查询用户,用表格显示,并把每个用户的所有地址显示出来那么问题来了按照上面的查询返回的分页的数据是没有问题的,但是分页的总记录数却是不对的。比如查出来的数据(数据库数据,并非页面显示)如下:
u_idusernamea_iddetail 1user11北京市海淀区 1user12北京市朝阳区 2user23天津市因为我的需求是分页显示用户,所以一个用户就是一条数据在页面显示大概是这样子,理论上是两条数据,
用户id用户名地址 1user1 1. 北京市海淀区 2. 北京市朝阳区 2user21. 天津市 共1页,共2条数据,每页显示10条但是,按mybatis的find_count配置 查出来是3条,这种问题如何解决?查询count(*)的时候将所有left join 后面关联的表去除吗?这样会不会导致返回的数据不准确
补充说明:感觉大家是理解错我的意思了,其实我这个问题主要是在SQL 上,而不再mybatis上,因为我查询出来的数据映射完毕之后是完全没有问题的,只是在分页的总记录数上出现了问题,导致分页不正确
问题解答
回答1:刚才写了个例子测了一下
`
两个实体类public class User {
private int id;private String username; // 用户名private List<Address> addresses;
public class Address {
private int id;private String detail; // 详细地址private int user_id; // 所属用户
映射文件<resultMap type='com.atguigu.mybatis.entity.User' autoMapping='true'>
<result property='id' column='u_id'/> <collection property='addresses' ofType='com.atguigu.mybatis.entity.Address' autoMapping='true'><result property='id' column='a_id'/><result property='user_id' column='u_id'/> </collection></resultMap><select resultMap='userMap' >
<!-- select tu.,ta., --><!-- ta.id as ’a_id’, --><!-- tu.id as ’u_id’ --><!-- from t_user tu , --><!-- t_address ta where ta.user_id=tu.id -->
select tu.*,ta.*, ta.id as ’a_id’, tu.id as ’u_id’ from t_user tu left join t_address ta on ta.user_id=tu.id </select>
测试结果
封装成的 List<User>的size是没问题的
回答2:关键词group by 自己查一下具体操作
回答3:SELECT *, ta.id AS ’a_id’, tu.id AS ’u_id’FROM t_user tuLEFT JOIN t_address ta ON ta.user_id = tu.id;
你希望想要两条 但是你的sql查出三条,所以显示错误,应该拆分逻辑:应该先查出你想要的用户
<select resultType='User' parameterType='map'>select *from t_user tu <where> <if test='name != null'>(username like #{name}) </if></where><if test='sort != null'> order by ${sort} <choose><when test='order != null'>${order}</when><otherwise>asc</otherwise> </choose> </if>limit #{pageOffset},#{pageSize} </select>
然后在
<resultMap type='User' autoMapping='true'><id property='id' column='u_id'/><collection ' property='addresses' javaType= 'ArrayList' column='u_id' ofType='Address' select= '??' /> </resultMap>
??是自己实现个 用userId查List<Address>的方法
回答4:这种情况不能这么分页,你需要对主表数据进行分页。
本来查询出100条数据,由于一对多会折叠去重很多数据,导致实际结果少于100条。
这种情况下可以采取嵌套查询方式解决,就是需要N+1次执行,可以懒加载。
或者看这里:https://my.oschina.net/flags/...
有关 MyBatis 内容可以访问:http://mybatis.tk
回答5:<select resultType='int' parameterType='map'> select count(*) from t_user tu left join t_address ta on ta.user_id=tu.id <where> <if test='name != null'> (username like #{name})</if> </where></select>
改:
<select resultType='int' parameterType='map'> select count(*) from t_user tu <where> <if test='name != null'> (username like #{name})</if> </where> group by username</select> 回答6:
用子查询就不会有问题了
select count(*) from ( // query 在这里即使关联100张表, 也不可能存在问题)
楼主可以看一下Mybatis-PageHelper count sql 转换实现
建议楼主直接使用 Mybatis-PageHelper 实现分页
相关文章:
1. paramiko - Python tempfile生成的文件能不能拷贝到远程服务器?2. javascript - IOS没有上APP Store如何实现热更新?3. URL访问有问题啊4. html标签属性元素讲解5. 网页爬虫 - Python爬虫返回状态码与实际情况不符?6. mysql - oracle物化视图和临时表的区别是什么?7. MYSQL代码执行错误:FUNCTION any_value does not exist8. node.js - nodejs开发中常用的连接mysql的库9. 微信小程序如何加载h5页面10. python - 能通过CAN控制一部普通的家用轿车吗?