mybatis開發(fā)dao得方法
SqlSession使用范圍
SqlSessionFactoryBuilder
通過SqlSessionFactoryBuilder創(chuàng)建會話工廠SqlSessionFactory
將SqlSessionFactoryBuilder當成一個工具類使用即可,不需要使用單例管理SqlSessionFactoryBuilder。
在需要創(chuàng)建SqlSessionFactory時候,只需要new一次SqlSessionFactoryBuilder即可。SqlSessionFactory
通過SqlSessionFactory創(chuàng)建SqlSession,使用單例模式管理sqlSessionFactory(工廠一旦創(chuàng)建,使用一個實例)。
將來mybatis和spring整合后,使用單例模式管理sqlSessionFactory。SqlSession
SqlSession是一個面向用戶(程序員)的接口。
SqlSession中提供了很多操作數(shù)據(jù)庫的方法:如:selectOne(返回單個對象)、selectList(返回單個或多個對象)、。
SqlSession是線程不安全的,在SqlSesion實現(xiàn)類中除了有接口中的方法(操作數(shù)據(jù)庫的方法)還有數(shù)據(jù)域?qū)傩浴?br> SqlSession最佳應用場合在方法體內(nèi),定義成局部變量使用。
原始dao開發(fā)方法(程序員需要寫dao接口和dao實現(xiàn)類)
思路
程序員需要寫dao接口和dao實現(xiàn)類。
需要向dao實現(xiàn)類中注入SqlSessionFactory,在方法體內(nèi)通過SqlSessionFactory創(chuàng)建SqlSessiondao接口
package cn.itcast.mybatis.dao;
import java.util.List;
import cn.itcast.mybatis.po.User;
/*
* 用戶管理
* */
public interface UserDao {
//根據(jù)id查詢用戶信息
public User findUserById(int id) throws Exception;
//根據(jù)用戶名列查詢用戶列表
public List<User> findUserByName(String name) throws Exception;
//添加用戶信息
public void insertUser(User user) throws Exception;
//刪除用戶信息
public void deleteUser(int id) throws Exception;
}
- dao實現(xiàn)類
package cn.itcast.mybatis.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import cn.itcast.mybatis.po.User;
public class UserDaoImpl implements UserDao {
//需要向dao實現(xiàn)類中注入SqlSessionFactory
//這里通過構造方法注入
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
// TODO 自動生成的方法存根
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("test.findUserById", id);
//釋放資源
sqlSession.close();
return user;
}
@Override
public List<User> findUserByName(String name) throws Exception {
// TODO 自動生成的方法存根
return null;
}
@Override
public void insertUser(User user) throws Exception {
// TODO 自動生成的方法存根
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser",user);
//提交事務
sqlSession.commit();
//釋放資源
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
// TODO 自動生成的方法存根
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete("test.deleteUser",id);
//提交事務
sqlSession.commit();
//釋放資源
sqlSession.close();
}
}
- 測試代碼
package cn.itcast.mybatis.dao;
import static org.junit.Assert.*;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.itcast.mybatis.po.User;
public class UserDaoImplTest {
private SqlSessionFactory sqlSessionFactory;
//此方法是在執(zhí)行testFindUserById之前執(zhí)行
@Before
public void setUp() throws Exception{
//創(chuàng)建sqlSessionFactory
//mybatis配置文件
String resource = "SqlMapConfig.xml";
//得到配置問價流
InputStream inputStream = Resources.getResourceAsStream(resource);
//創(chuàng)建會話工廠,傳入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
//創(chuàng)建UserDao的對象
UserDao userDao = new UserDaoImpl(sqlSessionFactory);
//調(diào)用UserDao的方法
User user = userDao.findUserById(1);
System.out.println(user);
}
}

總結原始dao開發(fā)問題
1、dao接口實現(xiàn)類方法中存在大量模板方法,設想能否將這些代碼提取出來,大大減輕程序員的工作量。

2、調(diào)用sqlsession方法時將statement的id硬編碼了

3、調(diào)用sqlsession方法時傳入的變量,由于sqlsession方法使用泛型,即使變量類型傳入錯誤,在編譯階段也不報錯,不利于程序員開發(fā)。

mapper代理方法(程序員只需要mapper接口(相當 于dao接口))
- 思路
程序員還需要編寫mapper.xml映射文件
程序員編寫mapper接口需要遵循一些開發(fā)規(guī)范,mybatis可以自動生成mapper接口實現(xiàn)類代理對象。
開發(fā)規(guī)范
- 在mapper.xml中namespace等于mapper接口地址

mapper.java接口中的方法名和mapper.xml中statement的id一致
mapper.java接口中的方法輸入?yún)?shù)類型和mapper.xml中statement的parameterType指定的類型一致
mapper.java接口中的方法返回值類型和mapper.xml中statement的resultType指定的類型一致。
- mapper.xml

- mapper.java

總結:
以上開發(fā)規(guī)范主要是對下邊的代碼進行統(tǒng)一生成:
User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);
- 在SqlMapConfig.xml中加載mapper.xml
<!-- 加載映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
- 測試
package cn.itcast.mybatis.mapper;
import static org.junit.Assert.*;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.itcast.mybatis.po.User;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception{
//創(chuàng)建sqlSessionFactory
//mybatis配置文件
String resource = "SqlMapConfig.xml";
//得到配置問價流
InputStream inputStream = Resources.getResourceAsStream(resource);
//創(chuàng)建會話工廠,傳入mybatis的配置文件信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper的對象,mybatis自動生成mapper代理對對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//調(diào)用UserMapper的方法
User user = userMapper.findUserById(1);
System.out.println(user);
}
}


- 總結


- 代理對象內(nèi)部調(diào)用selectOne或selectList
如果mapper方法返回單個pojo對象(非集合對象),代理對象內(nèi)部通過selectOne查詢數(shù)據(jù)庫。
如果mapper方法返回集合對象,代理對象內(nèi)部通過selectList查詢數(shù)據(jù)庫。
- mapper接口方法參數(shù)只能有一個是否影響系統(tǒng)開發(fā)
mapper接口方法參數(shù)只能有一個,系統(tǒng)是否不利于擴展維護。
系統(tǒng) 框架中,dao層的代碼是被業(yè)務層公用的。
即使mapper接口只有一個參數(shù),可以使用包裝類型的pojo滿足不同的業(yè)務方法的需求。
注意:持久層方法的參數(shù)可以包裝類型、map。。。,service方法中建議不要使用包裝類型(不利于業(yè)務層的可擴展)。
SqlMapConfig.xml
mybatis的全局配置文件SqlMapConfig.xml,配置內(nèi)容如下:
properties(屬性)
settings(全局配置參數(shù))
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環(huán)境集合屬性對象)
????environment(環(huán)境子屬性對象)
??????????transactionManager(事務管理)
??????????dataSource(數(shù)據(jù)源)
mappers(映射器)
屬性properties
需求:
將數(shù)據(jù)庫連接參數(shù)單獨配置在db.properties中,只需要在SqlMapConfig.xml中加載db.properties的屬性值。
在SqlMapConfig.xml中就不需要對數(shù)據(jù)庫連接參數(shù)硬編碼。
將數(shù)據(jù)庫連接參數(shù)只配置在db.properties中,原因:方便對參數(shù)進行統(tǒng)一管理,其它xml可以引用該db.properties。
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=suntong
在sqlMapConfig.xml加載屬性文件:
<properties resource="db.propertiees"></properties>
<!-- 和spring整合后 environments配置將廢除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事務管理-->
<transactionManager type="JDBC" />
<!-- 數(shù)據(jù)庫連接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
properties特性:
注意: MyBatis 將按照下面的順序來加載屬性:
在 properties 元素體內(nèi)定義的屬性首先被讀取。
然后會讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。
最后讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性。
建議:
不要在properties元素體內(nèi)添加任何屬性值,只將屬性值定義在properties文件中。

在properties文件中定義屬性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX
settings全局參數(shù)配置
mybatis框架在運行時可以調(diào)整一些運行參數(shù)。
比如:開啟二級緩存、開啟延遲加載。。
全局參數(shù)將會影響mybatis的運行行為。
詳細參見“學習資料/mybatis-settings.xlsx”文件



typeAliases(別名)
- 需求
在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入?yún)?shù)的類型、需要resultType指定輸出結果的映射類型。
如果在指定類型時輸入類型全路徑,不方便進行開發(fā),可以針對parameterType或resultType指定的類型定義一些別名,在mapper.xml中通過別名定義,方便開發(fā)。
-
mybatis默認支持別名
自定義別名
- 單個別名定義
<!-- 別名定義 -->
<typeAliases>
<!-- 針對單個別名的定義
type:類型的路徑
alias:別名
-->
<typeAlias type="cn.itcast.mybatis.po.User" alias="user"/>
</typeAliases>
引用
UserMapper.xml
<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id = #{id}
</select>
結果

- 批量別名定義
<!-- 批量別名的定義
指定包名:mybatis會自動掃描包中的po類,自動定義別名,別名就是類名,首字母大小寫都可以
-->
<package name="cn.itcast.mybatis.po"/>
還是可以

想選中多個包得自己一條一條的弄
不同包下有同名文件
<!-- 別名定義 -->
<typeAliases>
<!-- 針對單個別名的定義
type:類型的路徑
alias:別名
<typeAlias type="cn.itcast.mybatis.po.User" alias="user"/>
-->
<!-- 批量別名的定義
指定包名:mybatis會自動掃描包中的po類,自動定義別名,別名就是類名,首字母大小寫都可以
-->
<package name="cn.itcast.mybatis.po"/>
<package name="haha"/>
</typeAliases>


改變包的調(diào)用順序
<package name="haha"/>
<package name="cn.itcast.mybatis.po"/>

照錯不誤
類型處理器typeHandlers
mybatis中通過typeHandlers完成jdbc類型和java類型的轉(zhuǎn)換。
通常情況下,mybatis提供的類型處理器滿足日常需要,不需要自定義.
mybatis支持類型處理器:

objectFactory(對象工廠)
plugins(插件)
一般不用
mappers映射配置
- 加載單個映射文件
<!-- 加載映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
- 通過mapper接口加載單個映射文件
SqlMapConfig.xml
<!-- 加載映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
<!--
<mapper resource="mapper/UserMapper.xml"/>
通過mapper接口加載映射文件
需要遵頊一些規(guī)范:需要將mapper接口的類名和mapper.xml映射文件名稱保持一致,且在一個目錄
前提是使用mapper代理的方法
-->
<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
</mappers>

沒問題

- 批量加載多個mapper
<!-- 批量加載mapper
指定mapper接口的包名,mybatis自動掃描包下所有mapper接口進行加載
遵頊同樣的規(guī)范:需要將mapper接口的類名和mapper.xml映射文件名稱保持一致,且在一個目錄
前提是使用mapper代理的方法
-->
<package name="cn.itcast.mybatis.mapper"/>
ok

輸入映射
通過parameterType指定輸入?yún)?shù)的類型,類型可以是簡單類型、hashmap、pojo的包裝類型
傳遞pojo的包裝對象
需求
完成用戶信息的綜合查詢,需要傳入查詢條件很復雜(可能包括用戶信息、其它信息,比如商品、訂單的)定義包裝類型pojo
針對上邊需求,建議使用自定義的包裝類型的pojo。
在包裝類型的pojo中將復雜的查詢條件包裝進去。
UserQueryVo.java
package cn.itcast.mybatis.po;
/*
* 用戶的包裝類型
*
* Vo:視圖對象
* Po:持久層對象
* Pojo:自定義的簡單的bean對象
* */
public class UserQueryVo {
//在這里包裝所需要的查詢條件
//用戶查詢條件
private UserCustom userCustome;
/**
* @return userCustome
*/
public UserCustom getUserCustome() {
return userCustome;
}
/**
* @param userCustome 要設置的 userCustome
*/
public void setUserCustome(UserCustom userCustome) {
this.userCustome = userCustome;
}
//可以包裝其他的查詢條件,訂單、商品
}
用戶擴展類
UserCustom.java
package cn.itcast.mybatis.po;
/*
* 用戶的擴展類
* */
public class UserCustom extends User{
//在這里可以擴展用戶信息
}
-
mapper.xml
在UserMapper.xml中定義用戶信息綜合查詢(查詢條件復雜,通過高級查詢進行復雜關聯(lián)查詢)。
UserMapper.xml
<!-- 用戶信息的綜合查詢 這里用的是別名,因為剛才已經(jīng)批量掃描了
#{userCustom.sex}:取出包裝對象中性別的值
%${userCustom.username}%:取出pojo包裝對象中用戶的名稱
-->
<select id="findUserList" parameterType="UserQueryVo" resultType="UserCustom">
SELECT * FROM user WHERE user.sex = #{userCustom.sex} AND user.username LIKE '%${userCustom.username}%'
</select>
-
mapper.java
UserMapper
//用戶信息的綜合查詢
public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
- 測試代碼
//用戶信息的綜合查詢
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper的對象,mybatis自動生成mapper代理對對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//創(chuàng)建包裝類型,設置查詢條件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
userCustom.setSex("1");
userCustom.setUsername("張三豐");
userQueryVo.setUserCustome(userCustom);
//調(diào)用UserMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
System.out.println(list);
}

輸出映射
resultType
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo中的屬性名全部不一致,沒有創(chuàng)建pojo對象。
只要查詢出來的列名和pojo中的屬性有一個一致,就會創(chuàng)建pojo對象。
- 輸出簡單類型
需求
用戶信息的綜合查詢列表總數(shù),通過查詢總數(shù)和上邊用戶綜合查詢列表才可以實現(xiàn)分頁。mapper.xml
<!-- 用戶信息的綜合查詢總數(shù)
輸入類型一樣
輸出類型為簡單類型
-->
<select id="findUserCount" parameterType="UserQueryVo" resultType="int">
SELECT count(*) FROM user WHERE user.sex = #{userCustom.sex} AND user.username LIKE '%${userCustom.username}%'
</select>
- mapper.java
//用戶信息的綜合查詢總數(shù)
public int findUserCount(UserQueryVo userQueryVo) throws Exception;
- 測試代碼
//用戶信息的綜合查詢總數(shù)
@Test
public void testFindUserCount() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper的對象,mybatis自動生成mapper代理對對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//創(chuàng)建包裝類型,設置查詢條件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
userCustom.setSex("1");
userCustom.setUsername("張三豐");
userQueryVo.setUserCustome(userCustom);
//調(diào)用UserMapper的方法
int count = userMapper.findUserCount(userQueryVo);
System.out.println(count);
}

- 小結
查詢出來的結果集只有一行且一列,可以使用簡單類型進行輸出映射
- 輸出pojo對象和pojo列表
不管是輸出的pojo單個對象還是一個列表(list中包括pojo),在mapper.xml中resultType指定的類型是一樣的。
在mapper.java指定的方法返回值類型不一樣:
輸出單個pojo對象,方法返回值是單個對象類型

輸出pojo對象list,方法返回值是List<Pojo>

生成的動態(tài)代理對象中是根據(jù)mapper方法的返回值類型確定是調(diào)用selectOne(返回單個對象調(diào)用)還是selectList返回集合對象調(diào)用 )
resultMap
mybatis中使用resultMap完成高級輸出結果映射。
-
resultMap使用方法
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關系。
定義resultMap
使用resultMap作為statement的輸出映射類型
- 將下邊的sql使用User完成映射
SELECT id id_,username username_ FROM USER WHERE id=#{value}
User類中屬性名和上邊查詢列名不一致。
- 定義resultMap
<!-- 定義resultMap
將查詢出來的列和user類中的屬性做一個映射關系
type:resultMap最終所映射的java對象類型
id:對resultMap的唯一標識
-->
<resultMap type="user" id="userResultMap">
<!-- id表示查詢結果集中唯一標識
column:查詢出來的列名
property:type所指定的pojo類型中的屬性名
最終resultMap對column和property做一個映射關系(對應關系)
-->
<id column="id_" property="id"/>
<!-- 對普通列的映射定義
column:查詢出來的列名
property:type所指定的pojo類型中的屬性名
-->
<result column="username_" property="username"/>
</resultMap>
- 使用resultMap作為statement的輸出映射類型
<!-- 使用resultMap進行輸出的映射
resultMap:指定義的resultMap的id,如果這個resultMap再其他的mapper文件,前邊需要namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_ FROM USER WHERE id=#{value}
</select>
- mapper.java
//根據(jù)id查詢用戶信息,使用resultMap輸出
public User findUserByIdResultMap(int i) throws Exception;
- 測試
@Test
public void testFindUserByIdResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper的對象,mybatis自動生成mapper代理對對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//調(diào)用UserMapper的方法
User user = userMapper.findUserByIdResultMap(1);
System.out.println(user);
}

小結
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關系。
動態(tài)sql
什么是動態(tài)sql
mybatis核心對sql語句進行靈活操作,通過表達式進行判斷,對sql進行靈活拼接、組裝。
需求
用戶信息綜合查詢列表和用戶信息查詢列表總數(shù)這兩個statement的定義使用動態(tài)sql。
對查詢條件進行判斷,如果輸入?yún)?shù)不為空才進行查詢條件拼接。
mapper.xml
<!-- 用戶信息的綜合查詢 這里用的是別名,因為剛才已經(jīng)批量掃描了
#{userCustom.sex}:取出包裝對象中性別的值
%${userCustom.username}%:取出pojo包裝對象中用戶的名稱
-->
<select id="findUserList" parameterType="UserQueryVo" resultType="UserCustom">
SELECT * FROM user
<!-- 可以自動去掉條件中的第一個and -->
<where>
<if test="userCustom != null">
<if test="userCustom.sex != null and userCustom.sex != ''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username != null and userCustom.username != ''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</where>
</select>
<!-- 用戶信息的綜合查詢總數(shù)
輸入類型一樣
輸出類型為簡單類型
-->
<select id="findUserCount" parameterType="UserQueryVo" resultType="int">
SELECT count(*) FROM user WHERE
<where>
<if test="userCustom != null">
<if test="userCustom.sex != null and userCustom.sex != ''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username != null and userCustom.username != ''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</where>
</select>
測試代碼
//用戶信息的綜合查詢
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper的對象,mybatis自動生成mapper代理對對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//創(chuàng)建包裝類型,設置查詢條件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
//由于使用了動態(tài)sql,如果不設置某個值,條件不會拼接在sql中
//userCustom.setSex("1");
userCustom.setUsername("張三豐");
userQueryVo.setUserCustome(userCustom);
//調(diào)用UserMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
System.out.println(list);
}

sql片段
需求
將上邊實現(xiàn)的動態(tài)sql判斷代碼塊抽取出來,組成一個sql片段。其它的statement中就可以引用sql片段。
方便程序員進行開發(fā)。定義sql片段
<!-- 定義sql片段
id:sql片段的唯一標識
經(jīng)驗:是基于單表來當以,這樣sql片段的可重用性才高
在sql片段中不要包括where
-->
<sql id="query_user_where">
<if test="userCustom != null">
<if test="userCustom.sex != null and userCustom.sex != ''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username != null and userCustom.username != ''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</sql>
-
引用sql片段
在mapper.xml中定義的statement中引用sql片段:
<!-- 用戶信息的綜合查詢 這里用的是別名,因為剛才已經(jīng)批量掃描了
#{userCustom.sex}:取出包裝對象中性別的值
%${userCustom.username}%:取出pojo包裝對象中用戶的名稱
-->
<select id="findUserList" parameterType="UserQueryVo" resultType="UserCustom">
SELECT * FROM user
<!-- 可以自動去掉條件中的第一個and
refid:引用sql片段的id,如果refid指定的id不在本mapper文件中,需要在前邊加namespace
-->
<where>
<include refid="query_user_where"></include>
<!-- 在這里還會引用其他的sql片段 -->
</where>
成功引用

foreach標簽
向sql傳遞數(shù)組或List,mybatis使用foreach解析
-
需求
在用戶查詢列表和查詢總數(shù)的statement中增加多個id輸入查詢。
sql語句如下:
兩種方法:
SELECT * FROM USER WHERE id=1 OR id=10 OR id=16
SELECT * FROM USER WHERE id IN(1,10,16)
- 在輸入?yún)?shù)類型中添加List<Integer> ids傳入多個id
UserQueryVo.java
//傳入多個id
private List<Integer> ids;
/**
* @return ids
*/
public List<Integer> getIds() {
return ids;
}
/**
* @param ids 要設置的 ids
*/
public void setIds(List<Integer> ids) {
this.ids = ids;
}
-
修改mapper.xml
WHERE id=1 OR id=10 OR id=16
在查詢條件中,查詢條件定義成一個sql片段,需要修改sql片段。
<sql id="query_user_where">
<if test="userCustom != null">
<if test="userCustom.sex != null and userCustom.sex != ''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username != null and userCustom.username != ''">
and user.username LIKE '%${userCustom.username}%'
</if>
<if test="ids != null">
<!-- 使用foreach遍歷傳入ids
collection:指定輸入對象中聚合屬性
item:每次遍歷生成對象名
open:開始遍歷時要拼接的串
close:結束遍歷時所要拼接的串
separator:遍歷的兩個對象中間所要拼接的串
-->
<!-- 如:實現(xiàn)下面的sql拼接
AND (id = 1 OR id = 16 OR id = 19)
-->
<foreach collection="ids" item="user_id" open="AND (" close=")" separator="OR">
<!-- 每次遍歷需要拼接的串 -->
id = #{user_id}
</foreach>
</if>
</if>
</sql>
- 測試代碼
//用戶信息的綜合查詢
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創(chuàng)建UserMapper的對象,mybatis自動生成mapper代理對對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//創(chuàng)建包裝類型,設置查詢條件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
//由于使用了動態(tài)sql,如果不設置某個值,條件不會拼接在sql中
//userCustom.setSex("1");
userCustom.setUsername("張三豐");
//傳入多個id
List<Integer> ids = new ArrayList<Integer>();
ids.add(24);
ids.add(25);
ids.add(26);
userQueryVo.setIds(ids);
userQueryVo.setUserCustome(userCustom);
//調(diào)用UserMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
System.out.println(list);
}

完整界面

