02 mybatis開發(fā)

mybatis開發(fā)dao得方法

SqlSession使用范圍

  1. SqlSessionFactoryBuilder
    通過SqlSessionFactoryBuilder創(chuàng)建會話工廠SqlSessionFactory
    將SqlSessionFactoryBuilder當成一個工具類使用即可,不需要使用單例管理SqlSessionFactoryBuilder。
    在需要創(chuàng)建SqlSessionFactory時候,只需要new一次SqlSessionFactoryBuilder即可。

  2. SqlSessionFactory
    通過SqlSessionFactory創(chuàng)建SqlSession,使用單例模式管理sqlSessionFactory(工廠一旦創(chuàng)建,使用一個實例)。
    將來mybatis和spring整合后,使用單例模式管理sqlSessionFactory。

  3. 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)類)

  1. 思路
    程序員需要寫dao接口和dao實現(xiàn)類。
    需要向dao實現(xiàn)類中注入SqlSessionFactory,在方法體內(nèi)通過SqlSessionFactory創(chuàng)建SqlSession

  2. dao接口

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;
}

  1. 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();
        
    }

}

  1. 測試代碼
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接口))

  1. 思路

程序員還需要編寫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指定的類型一致。

  1. mapper.xml
  1. mapper.java

總結:
以上開發(fā)規(guī)范主要是對下邊的代碼進行統(tǒng)一生成:

User user = sqlSession.selectOne("test.findUserById", id);
sqlSession.insert("test.insertUser", user);

  1. 在SqlMapConfig.xml中加載mapper.xml
<!-- 加載映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
        
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
  1. 測試
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);
        
    }

}

  1. 總結
  • 代理對象內(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(別名)

  1. 需求

在mapper.xml中,定義很多的statement,statement需要parameterType指定輸入?yún)?shù)的類型、需要resultType指定輸出結果的映射類型。

如果在指定類型時輸入類型全路徑,不方便進行開發(fā),可以針對parameterType或resultType指定的類型定義一些別名,在mapper.xml中通過別名定義,方便開發(fā)。

  1. mybatis默認支持別名

  2. 自定義別名

  • 單個別名定義
<!-- 別名定義 -->
    <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映射配置

  1. 加載單個映射文件
<!-- 加載映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml"/>
        
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
  1. 通過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>

沒問題

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

ok

輸入映射

通過parameterType指定輸入?yún)?shù)的類型,類型可以是簡單類型、hashmap、pojo的包裝類型

傳遞pojo的包裝對象

  1. 需求
    完成用戶信息的綜合查詢,需要傳入查詢條件很復雜(可能包括用戶信息、其它信息,比如商品、訂單的)

  2. 定義包裝類型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{

    //在這里可以擴展用戶信息
    
    
    
}

  1. 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>
  1. mapper.java
    UserMapper
//用戶信息的綜合查詢
    public List<UserCustom> findUserList(UserQueryVo userQueryVo) throws Exception;
  1. 測試代碼
//用戶信息的綜合查詢
    @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對象。

  1. 輸出簡單類型
  • 需求
    用戶信息的綜合查詢列表總數(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);
            
        }
  • 小結
    查詢出來的結果集只有一行且一列,可以使用簡單類型進行輸出映射
  1. 輸出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完成高級輸出結果映射。

  1. resultMap使用方法
    如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關系。

定義resultMap

使用resultMap作為statement的輸出映射類型

  1. 將下邊的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片段

  1. 需求
    將上邊實現(xiàn)的動態(tài)sql判斷代碼塊抽取出來,組成一個sql片段。其它的statement中就可以引用sql片段。
    方便程序員進行開發(fā)。

  2. 定義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>
  1. 引用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解析

  1. 需求
    在用戶查詢列表和查詢總數(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)

  1. 在輸入?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;
    }
  1. 修改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>
  1. 測試代碼
//用戶信息的綜合查詢
    @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);
        
    }

完整界面

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容