parameterType(輸入類型)
傳遞簡單類型
使用#{}占位符,或者${}進(jìn)行sql拼接
傳遞pojo對象
Mybatis使用ognl表達(dá)式解析對象字段的值,#{}或者${}括號(hào)中的值為pojo屬性名稱
傳遞pojo包裝對象
開發(fā)中通過可以使用pojo傳遞查詢條件
查詢條件可能是綜合的查詢條件,不僅包括用戶查詢條件還包括其它的查詢條件(比如查詢用戶信息的時(shí)候,將用戶購買商品信息也作為查詢條件),這時(shí)可以使用包裝對象傳遞輸入?yún)?shù)
包裝對象:Pojo類中的一個(gè)屬性是另外一個(gè)pojo
需求:根據(jù)用戶名模糊查詢用戶信息,查詢條件放到QueryVo的user屬性中
- 編寫QueryVo
package com.cuzz.pojo;
public class QueryVo {
// 包含其他pojo
public User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
- sql語句
SELECT * FROM user WHERE username LIKE '%張%' - Mapper.xml文件
<!-- 根據(jù)用戶的名模糊查詢 -->
<select id="queryUserByQueryVo" parameterType="QueryVo" resultType="com.cuzz.pojo.User">
SELECT * FROM `user` WHERE username LIKE "%"#{user.username}"%"
</select>
- Mapper接口
在UserMapper接口中添加方法
// 根據(jù)包裝類查詢用戶
List<User> queryUserByQueryVo(QueryVo queryVo);
- 測試方法
@Test
public void testQueryUserByQueryVo() {
// mybatis和spring整合,整合之后,交給spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 創(chuàng)建Mapper接口的動(dòng)態(tài)代理對象,整合之后,交給spring管理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用userMapper執(zhí)行查詢,使用包裝對象
QueryVo queryVo = new QueryVo();
// 設(shè)置user條件
User user = new User();
user.setUsername("張");
// 設(shè)置到包裝對象中
queryVo.setUser(user);
// 執(zhí)行查詢
List<User> list = userMapper.queryUserByQueryVo(queryVo);
for (User u : list) {
System.out.println(u);
}
// mybatis和spring整合,整合之后,交給spring管理
sqlSession.close();
}
resultType(輸出類型)
輸出簡單類型
- 需求:查詢用戶表數(shù)據(jù)條數(shù)
- Sql
SELECT count(*) FROM `user` - Mapper.xml文件
<!-- 查詢用戶的條數(shù) -->
<select id="queryUserCount" resultType="int">
SELECT count(*) FROM `user`
</select>
- Mapper接口
int queryUserCount();
輸出pojo對象
輸出pojo列表
resultMap(輸出類型)
resultType可以指定將查詢結(jié)果映射為pojo,但需要pojo的屬性名和sql查詢的列名一致方可映射成功。
如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個(gè)對應(yīng)關(guān)系 ,resultMap實(shí)質(zhì)上還需要將查詢結(jié)果映射到pojo對象中。
resultMap可以實(shí)現(xiàn)將查詢結(jié)果映射為復(fù)雜類型的pojo,比如在查詢結(jié)果映射對象中包括pojo和list實(shí)現(xiàn)一對一查詢和一對多查詢。
- 需求:查詢訂單表order的所有數(shù)據(jù)
- Sql
SELECT id, user_id, number, createtime, note FROM `order` -
數(shù)據(jù)表
image.png - order對象
public class Order {
// 訂單id
private int id;
// 用戶id
private Integer userId;
// 訂單號(hào)
private String number;
// 訂單創(chuàng)建時(shí)間
private Date createtime;
// 備注
private String note;
}
- Mapper.xml
<?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">
<!-- namespace:命名空間,用于隔離sql,還有一個(gè)很重要的作用,Mapper動(dòng)態(tài)代理開發(fā)的時(shí)候使用,需要指定Mapper的類路徑 -->
<mapper namespace="com.cuzz.mapper.OrderMapper">
<!-- 查詢所有的訂單數(shù)據(jù) -->
<select id="queryOrderAll" resultType="order">
SELECT id, user_id,
number,
createtime, note FROM `order`
</select>
</mapper>
- Mapper接口
public interface OrderMapper {
// 查詢所有訂單
List<Order> queryOrderAll();
}
- 發(fā)現(xiàn)userId為null
- 使用resultMap
由于上邊的mapper.xml中sql查詢列(user_id)和Order類屬性(userId)不一致,所以查詢結(jié)果不能映射到pojo中。
需要定義resultMap,把orderResultMap將sql查詢列(user_id)和Order類屬性(userId)對應(yīng)起來
<?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">
<!-- namespace:命名空間,用于隔離sql,還有一個(gè)很重要的作用,Mapper動(dòng)態(tài)代理開發(fā)的時(shí)候使用,需要指定Mapper的類路徑 -->
<mapper namespace="com.cuzz.mapper.OrderMapper">
<!-- resultMap最終還是要將結(jié)果映射到pojo上,type就是指定映射到哪一個(gè)pojo -->
<!-- id:設(shè)置ResultMap的id -->
<resultMap type="order" id="orderResultMap">
<!-- 定義主鍵 ,非常重要。如果是多個(gè)字段,則定義多個(gè)id -->
<!-- property:主鍵在pojo中的屬性名 -->
<!-- column:主鍵在數(shù)據(jù)庫中的列名 -->
<id property="id" column="id" />
<!-- 定義普通屬性 -->
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
</resultMap>
<!-- 查詢所有的訂單數(shù)據(jù) -->
<select id="queryOrderAll" resultMap="orderResultMap">
SELECT id, user_id,
number,
createtime, note FROM `order`
</select>
</mapper>
動(dòng)態(tài)SQL
通過mybatis提供的各種標(biāo)簽方法實(shí)現(xiàn)動(dòng)態(tài)拼接sql。
if 標(biāo)簽
- 需求:根據(jù)性別和名字查詢用戶
- 查詢sql:
SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%張%' - Mapper.xml
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
WHERE sex = #{sex} AND username LIKE
'%${username}%'
</select>
- Mapper接口
List<User> queryUserByWhere(User user); - 這樣很不合理,查詢條件越多我們就編寫越多的sql
- 使用if標(biāo)簽
修改Mapper.xml文件
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
WHERE 1=1
<if test="sex != null and sex != ''">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</select>
注意字符串類型的數(shù)據(jù)需要要做不等于空字符串校驗(yàn)。
where標(biāo)簽
上面的sql還有where 1=1 這樣的語句,很麻煩
可以使用where標(biāo)簽進(jìn)行改造
- 修改Mapper.xml
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
<!-- where標(biāo)簽可以自動(dòng)添加where,同時(shí)處理sql語句中第一個(gè)and關(guān)鍵字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>
SQL片段
- Sql中可將重復(fù)的sql提取出來,使用時(shí)用include引用即可,最終達(dá)到sql重用的目的。
= 把上面例子中的id, username, birthday, sex, address提取出來,作為sql片段,如下:
<!-- 根據(jù)條件查詢用戶 -->
<select id="queryUserByWhere" parameterType="user" resultType="user">
<!-- SELECT id, username, birthday, sex, address FROM `user` -->
<!-- 使用include標(biāo)簽加載sql片段;refid是sql片段id -->
SELECT <include refid="userFields" /> FROM `user`
<!-- where標(biāo)簽可以自動(dòng)添加where關(guān)鍵字,同時(shí)處理sql語句中第一個(gè)and關(guān)鍵字 -->
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>
<!-- 聲明sql片段 -->
<sql id="userFields">
id, username, birthday, sex, address
</sql>
- 如果要使用別的Mapper.xml配置的sql片段,可以在refid前面加上對應(yīng)的Mapper.xml的namespace
foreach 標(biāo)簽
- 向sql傳遞數(shù)組或List,mybatis使用foreach解析,如下:
- 需求:根據(jù)多個(gè)id查詢用戶信息
- 查詢Sql:
SELECT * FROM user WHERE id IN (1,10,24) - 改造QueryVo
在pojo中定義list屬性ids儲(chǔ)存多個(gè)用戶的id
public class QueryVo {
// 包含其他pojo
private User user;
private List<Integer> ids;
getter/setter
}
- Mapper.xml
<!-- 根據(jù)ids查詢用戶 -->
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
SELECT * FROM `user`
<where>
<!-- foreach標(biāo)簽,進(jìn)行遍歷 -->
<!-- collection:遍歷的集合,這里是QueryVo的ids屬性 -->
<!-- item:遍歷的項(xiàng)目,可以隨便寫,,但是和后面的#{}里面要一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在結(jié)尾處添加的sql片段 -->
<!-- separator:指定遍歷的元素之間使用的分隔符 -->
<foreach collection="ids" item="item" open="id IN (" close=")"
separator=",">
#{item}
</foreach>
</where>
</select>
關(guān)聯(lián)查詢
商品訂單數(shù)據(jù)模型
- 訂單表:order
記錄了用戶創(chuàng)建的訂單
創(chuàng)建用戶:user_id(外鍵)
訂單號(hào)
創(chuàng)建時(shí)間
訂單狀態(tài) - 用戶表:user
記錄了購買商品的用戶信息
Id:唯一標(biāo)識(shí)一個(gè)用戶 - 一對一:一個(gè)訂單只能由一個(gè)用戶創(chuàng)建
- 一對多:一個(gè)用戶可以創(chuàng)建多個(gè)訂單
一對一查詢
- 需求:查詢所有訂單信息,關(guān)聯(lián)查詢下單用戶信息。
- 注意:因?yàn)橐粋€(gè)訂單信息只會(huì)是一個(gè)人下的訂單,所以從查詢訂單信息出發(fā)關(guān)聯(lián)查詢用戶信息為一對一查詢。如果從用戶信息出發(fā)查詢用戶下的訂單信息則為一對多查詢,因?yàn)橐粋€(gè)用戶可以下多個(gè)訂單。
- Sql語句:
SELECT
o.id,
o.user_id userId,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
使用resultType
使用resultType,改造訂單pojo類,此pojo類中包括了訂單信息和用戶信息
這樣返回對象的時(shí)候,mybatis自動(dòng)把用戶信息也注入進(jìn)來了
- 改造pojo類
OrderUser類繼承Order類后OrderUser類包括了Order類的所有字段,只需要定義用戶的信息字段即可
package com.cuzz.pojo;
public class OrderUser extends Order{
private String username;
private String address;
}
- Mapper.xml
在UserMapper.xml添加sql,如下
<!-- 查詢訂單,同時(shí)包含用戶數(shù)據(jù) -->
<select id="queryOrderUser" resultType="orderUser">
SELECT
o.id,
o.user_id
userId,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
</select>
- Mapper接口
List<OrderUser> queryOrderUser(); - 小結(jié)
定義專門的pojo類作為輸出類型,其中定義了sql查詢結(jié)果集所有的字段。此方法較為簡單,企業(yè)中使用普遍。
使用resultMap
- 使用resultMap,定義專門的resultMap用于映射一對一查詢結(jié)果。
- 改造pojo類
在Order類中加入U(xiǎn)ser屬性,user屬性中用于存儲(chǔ)關(guān)聯(lián)查詢的用戶信息,因?yàn)橛唵侮P(guān)聯(lián)查詢用戶是一對一關(guān)系,所以這里使用單個(gè)User對象存儲(chǔ)關(guān)聯(lián)查詢的用戶信息
package com.cuzz.pojo;
public class Order {
// 訂單
private Integer id;
// 用戶id
private Integer userId;
// 訂單號(hào)
private String number;
// 備注
private String note;
// 用戶
private User user;
}
- Mapper.xml
這里resultMap指定orderUserResultMap,如下:
<resultMap type="order" id="orderUserResultMap">
<id property="id" column="id" />
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
<!-- association :配置一對一屬性 -->
<!-- property:order里面的User屬性名 -->
<!-- javaType:屬性類型 -->
<association property="user" javaType="user">
<!-- id:聲明主鍵,表示user_id是關(guān)聯(lián)查詢對象的唯一標(biāo)識(shí)-->
<id property="id" column="user_id" />
<result property="username" column="username" />
<result property="address" column="address" />
</association>
</resultMap>
<!-- 一對一關(guān)聯(lián),查詢訂單,訂單內(nèi)部包含用戶屬性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
SELECT
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
</select>
一對多查詢
- 案例:查詢所有用戶信息及用戶關(guān)聯(lián)的訂單信息。
用戶信息和訂單信息為一對多關(guān)系。 - Sql語句:
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime,
o.note
FROM
`user` u
LEFT JOIN `order` o ON u.id = o.user_id
- 修改pojo類
在User類中加入List<Order> orders屬性,如下圖:
public class User {
private int id;
private String username;
private String sex;
private Date birthday;
private String address;
private List<Order> orders;
}
- Mapper.xml
<resultMap type="user" id="userOrderResultMap">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="birthday" column="birthday" />
<result property="sex" column="sex" />
<result property="address" column="address" />
<!-- 配置一對多的關(guān)系 -->
<collection property="orders" javaType="list" ofType="order">
<!-- 配置主鍵,是關(guān)聯(lián)Order的唯一標(biāo)識(shí) -->
<id property="id" column="oid" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
</collection>
</resultMap>
<!-- 一對多關(guān)聯(lián),查詢訂單同時(shí)查詢該用戶下的訂單 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime,
o.note
FROM
`user` u
LEFT JOIN `order` o ON u.id = o.user_id
</select>
逆向工程
略
