舉例:
有兩個(gè)實(shí)體類(lèi)別 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; // 詳細(xì)地址
private User user; //所屬用戶
// getter setter...
}
資料庫(kù):
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" id="userMap" 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 id="find" 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 id="find_count" 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>
用戶和地址的關(guān)係為:一個(gè)用戶有多個(gè)地址,一個(gè)地址只能屬於一個(gè)用戶,一對(duì)多
假設(shè)現(xiàn)在的需求是,分頁(yè)查詢用戶,用表格顯示,並把每個(gè)用戶的所有位址顯示出來(lái)
那麼問(wèn)題來(lái)了
按照上面的查詢返回的分頁(yè)的資料是沒(méi)有問(wèn)題的,但是分頁(yè)的總記錄數(shù)卻是不對(duì)的。
例如查出來(lái)的數(shù)據(jù)(資料庫(kù)數(shù)據(jù),非頁(yè)面顯示)如下:
u_id | username | a_id | detail |
---|---|---|---|
1 | user1 | 1 | 北京市海淀區(qū) |
1 | user1 | 2 | 北京市朝陽(yáng)區(qū) |
2 | user2 | 3 | 天津市 |
因?yàn)槲业男枨笫欠猪?yè)顯示用戶,所以一個(gè)用戶就是一條數(shù)據(jù)在頁(yè)面顯示大概是這樣子,理論上是兩個(gè)數(shù)據(jù),
用戶id | 使用者名稱(chēng) | 地址 |
---|---|---|
1 | user1 | 1. 北市海淀區(qū) 2. 北京市朝陽(yáng)區(qū) |
2 | user2 | 1. 天津市 |
共1頁(yè),共2條數(shù)據(jù),每頁(yè)顯示10條 |
但是,按mybatis的find_count配置 查出來(lái)是3條,這種問(wèn)題如何解決?
查詢count(*)的時(shí)候?qū)⑺衛(wèi)eft join 後面關(guān)聯(lián)的表格移除嗎?這樣會(huì)不會(huì)導(dǎo)致回傳的資料不準(zhǔn)確
補(bǔ)充說(shuō)明:感覺(jué)大家是理解錯(cuò)我的意思了,其實(shí)我這個(gè)問(wèn)題主要是在SQL 上,而不再mybatis上,因?yàn)槲也樵兂鰜?lái)的資料映射完畢之後是完全沒(méi)有問(wèn)題的,只是在分頁(yè)的總記錄數(shù)上出現(xiàn)了問(wèn)題,導(dǎo)致分頁(yè)不正確
#人生最曼妙的風(fēng)景,竟是內(nèi)心的淡定與從容!
剛才寫(xiě)了個(gè)例子測(cè)了一下
`
兩個(gè)實(shí)體類(lèi)別
public class User {
private int id;
private String username; // 用戶名
private List<Address> addresses;
public class Address {
private int id;
private String detail; // 詳細(xì)地址
private int user_id; // 所屬用戶
映射檔
<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 id="select_all_user_address" resultMap="userMap" >
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>
測(cè)試結(jié)果
封裝成的 List
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;
你希望想要兩個(gè) 但是你的sql查出三條,所以顯示錯(cuò)誤,
應(yīng)該拆分邏輯:
應(yīng)該先查出你想要的用戶
<select id="find" 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" id="userMap" autoMapping="true">
<id property="id" column="u_id"/>
<collection " property="addresses" javaType= "ArrayList" column="u_id"
ofType="Address" select= "??" />
</resultMap>
??是自己實(shí)作個(gè) 用userId查L(zhǎng)ist
的方法這種情況不能這麼分頁(yè),你需要將主表資料分頁(yè)。
本來(lái)查詢出100條數(shù)據(jù),由於一對(duì)多會(huì)折疊去重很多數(shù)據(jù),導(dǎo)致實(shí)際結(jié)果少於100條。
這種情況下可以採(cǎi)取巢狀查詢方式解決,就是需要N+1次執(zhí)行,可以懶載入。
或看這裡:https://my.oschina.net/flags/...
有關(guān) MyBatis 內(nèi)容可以訪問(wèn):http://mybatis.tk
<select id="find_count" 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 id="find_count" resultType="int" parameterType="map">
select count(*)
from t_user tu
<where>
<if test="name != null">
(username like #{name})
</if>
</where>
group by username
</select>
用子查詢就不會(huì)有問(wèn)題了
select count(*) from (
// query 在這里即使關(guān)聯(lián)100張表, 也不可能存在問(wèn)題
)
樓主可以看一下Mybatis-PageHelper
count sql 轉(zhuǎn)換實(shí)作
建議樓主直接使用 Mybatis-PageHelper 實(shí)現(xiàn)分頁(yè)