java - Mybatis 數據庫多表關聯(lián)分頁的問題
問題描述
舉個例子:有兩個實體類 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北京市海淀區(qū) 1user12北京市朝陽區(qū) 2user23天津市因為我的需求是分頁顯示用戶,所以一個用戶就是一條數據在頁面顯示大概是這樣子,理論上是兩條數據,
用戶id用戶名地址 1user1 1. 北京市海淀區(qū) 2. 北京市朝陽區(qū) 2user21. 天津市 共1頁,共2條數據,每頁顯示10條但是,按mybatis的find_count配置 查出來是3條,這種問題如何解決?查詢count(*)的時候將所有l(wèi)eft join 后面關聯(lián)的表去除嗎?這樣會不會導致返回的數據不準確
補充說明:感覺大家是理解錯我的意思了,其實我這個問題主要是在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次執(zhí)行,可以懶加載。
或者看這里: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 在這里即使關聯(lián)100張表, 也不可能存在問題)
樓主可以看一下Mybatis-PageHelper count sql 轉換實現
建議樓主直接使用 Mybatis-PageHelper 實現分頁
相關文章:
1. javascript - ionic1的插件如何遷移到ionic2的項目中2. java - 如何在Fragment中調用Activity的onNewIntent?3. javascript - h5上的手機號默認沒有識別4. mysql里的大表用mycat做水平拆分,是不是要先手動分好,再配置mycat5. css - 關于input標簽disabled問題6. python - 獲取到的數據生成新的mysql表7. 怎么用css截取字符?8. window下mysql中文亂碼怎么解決??9. javascript - jquery hide()方法無效10. python的文件讀寫問題?
