舉例:
有兩個實體類別 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" 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>
用戶和地址的關係為:一個用戶有多個地址,一個地址只能屬於一個用戶,一對多
假設現在的需求是,分頁查詢用戶,用表格顯示,並把每個用戶的所有位址顯示出來
那麼問題來了
按照上面的查詢返回的分頁的資料是沒有問題的,但是分頁的總記錄數卻是不對的。
例如查出來的數據(資料庫數據,非頁面顯示)如下:
u_id | username | a_id | detail |
---|---|---|---|
1 | user1 | 1 | 北京市海淀區 |
1 | user1 | 2 | 北京市朝陽區 |
2 | user2 | 3 | 天津市 |
因為我的需求是分頁顯示用戶,所以一個用戶就是一條數據在頁面顯示大概是這樣子,理論上是兩個數據,
用戶id | 使用者名稱 | 地址 |
---|---|---|
1 | user1 | 1. 北市海淀區 2. 北京市朝陽區 |
2 | user2 | 1. 天津市 |
共1頁,共2條數據,每頁顯示10條 |
但是,按mybatis的find_count配置 查出來是3條,這種問題如何解決?
查詢count(*)的時候將所有left join 後面關聯的表格移除嗎?這樣會不會導致回傳的資料不準確
補充說明:感覺大家是理解錯我的意思了,其實我這個問題主要是在SQL 上,而不再mybatis上,因為我查詢出來的資料映射完畢之後是完全沒有問題的,只是在分頁的總記錄數上出現了問題,導致分頁不正確
#漂亮男人2017-06-10 09:51:39
剛才寫了個例子測了一下
`
兩個實體類別
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; // 所属用户
映射檔
<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" >
< !-- from t_user tu , -->
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
欧阳克2017-06-10 09:51:39
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;
你希望想要兩個 但是你的sql查出三條,所以顯示錯誤,
應該拆分邏輯:
應該先查出你想要的用戶
<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>
??是自己實作個 用userId查List
的方法欧阳克2017-06-10 09:51:39
這種情況不能這麼分頁,你需要將主表資料分頁。
本來查詢出100條數據,由於一對多會折疊去重很多數據,導致實際結果少於100條。
這種情況下可以採取巢狀查詢方式解決,就是需要N+1次執行,可以懶載入。
或看這裡:https://my.oschina.net/flags/...
有關 MyBatis 內容可以訪問:http://mybatis.tk
扔个三星炸死你2017-06-10 09:51:39
<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>
曾经蜡笔没有小新2017-06-10 09:51:39
用子查詢就不會有問題了
select count(*) from (
// query 在这里即使关联100张表, 也不可能存在问题
)
樓主可以看一下Mybatis-PageHelper
count sql 轉換實作
建議樓主直接使用 Mybatis-PageHelper 實現分頁