「Mybatis系列」Mybatis開發方式和配置

1. Mybatis的開發方式

此處使用的是JDK的動態代理方式,延遲加載使用的cglib動態代理方式java

1.1 代理理解

代理分爲靜態代理和動態代理。此處先不說靜態代理,由於Mybatis中使用的代理方式是動態代理。mysql

動態代理分爲兩種方式:sql

  • 基於JDK的動態代理--針對有接口的類進行動態代理
  • 基於CGLIB的動態代理--經過子類繼承父類的方式去進行代理。

1.2 XML方式

  • 開發方式

    只須要開發Mapper接口(dao接口)和Mapper映射文件,不須要編寫實現類。數據庫

  • 開發規範

    Mapper接口開發方式須要遵循如下規範:數組

    一、 Mapper接口的類路徑與Mapper.xml文件中的namespace相同。session

    二、 Mapper接口方法名稱和Mapper.xml中定義的每一個statement的id相同。mybatis

    三、 Mapper接口方法的輸入參數類型和mapper.xml中定義的每一個sql 的parameterType的類型相同。app

    四、 Mapper接口方法的返回值類型和mapper.xml中定義的每一個sql的resultType的類型相同。測試

  • mapper映射文件
<?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="com.kkb.mybatis.mapper.UserMapper">
<!-- 根據id獲取用戶信息 -->
    <select id="findUserById" parameterType="int" resultType="com.kkb.mybatis.po.User">
        select * from user where id = #{id}
    </select>
</mapper>
  • mapper接口
/**
 * 用戶管理mapper
 */
public interface UserMapper {
    //根據用戶id查詢用戶信息
    public User findUserById(int id) throws Exception;
}
  • 全局配置文件中加載映射文件
<!-- 加載映射文件 -->
  <mappers>
    <mapper resource="mapper/UserMapper.xml"/>
  </mappers>
  • 測試代碼
public class UserMapperTest{

    private SqlSessionFactory sqlSessionFactory;

@Before
    public void setUp() throws Exception {
        //mybatis配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //使用SqlSessionFactoryBuilder建立sessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void testFindUserById() throws Exception {
        //獲取session
        SqlSession session = sqlSessionFactory.openSession();
        //獲取mapper接口的代理對象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //調用代理對象方法
        User user = userMapper.findUserById(1);
        System.out.println(user);
        //關閉session
        session.close();
        
    }
}

1.3 註解方式

  • 開發方式

    只須要編寫mapper接口文件接口。ui

  • mapper接口
public interface AnnotationUserMapper {
    // 查詢
    @Select("SELECT * FROM user WHERE id = #{id}")
    public User findUserById(int id);

    // 模糊查詢用戶列表
    @Select("SELECT * FROM user WHERE username LIKE '%${value}%'")
    public List<User> findUserList(String username);

    // 添加並實現主鍵返回
    @Insert("INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},#{sex},#{address})")
    @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", resultType = int.class, before = false)
    public void insertUser(User user);

}
  • 測試代碼
public class AnnotationUserMapperTest {

    private SqlSessionFactory sqlSessionFactory;

    /**
     * @Before註解的方法會在@Test註解的方法以前執行
     * 
     * @throws Exception
     */
    @Before
    public void init() throws Exception {
        // 指定全局配置文件路徑
        String resource = "SqlMapConfig.xml";
        // 加載資源文件(全局配置文件和映射文件)
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 還有構建者模式,去建立SqlSessionFactory對象
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testFindUserById() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);

        User user = userMapper.findUserById(1);
        System.out.println(user);
    }

    @Test
    public void testFindUserList() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);

        List<User> list = userMapper.findUserList("老郭");
        System.out.println(list);
    }

    @Test
    public void testInsertUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AnnotationUserMapper userMapper = sqlSession.getMapper(AnnotationUserMapper.class);

        User user = new User();
        user.setUsername("開課吧-2");
        user.setSex("1");
        user.setAddress("致真大廈");
        userMapper.insertUser(user);
        System.out.println(user.getId());
    }

}

2. 全局配置文件

2.1 配置內容

SqlMapConfig.xml中配置的內容和順序以下:

properties(屬性)

settings(全局配置參數)

typeAliases(類型別名)

typeHandlers(類型處理器)--Java類型--JDBC類型--->數據庫類型轉換

objectFactory(對象工廠)

plugins(插件)--能夠在Mybatis執行SQL語句的流程中,橫叉一腳去實現一些功能加強,好比PageHelper分頁插件,就是第三方實現的一個插件

environments(環境集合屬性對象)

environment(環境子屬性對象)
       transactionManager(事務管理)
       dataSource(數據源)
mappers(映射器)

2.2 properties標籤

SqlMapConfig.xml能夠引用java屬性文件中的配置信息。

一、在classpath下定義db.properties文件,

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

二、在SqlMapConfig.xml文件中,引用db.properties中的屬性,具體以下:

<properties resource="db.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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標籤除了可使用resource屬性,引用properties文件中的屬性。還能夠在properties標籤內定義property子標籤來定義屬性和屬性值,具體以下:

<properties>
    <property name="driver" value="com.mysql.jdbc.Driver"/>
</properties>

注意: MyBatis 將按照下面的順序來加載屬性

  • 讀取properties 元素體內定義的屬性。
  • 讀取properties 元素中resource或 url 加載的屬性,它會覆蓋已讀取的同名屬性。

2.3 typeAlias標籤

別名的做用:就是爲了簡化映射文件中parameterType和ResultType中的POJO類型名稱編寫。

2.3.1 默認支持別名

別名 映射的類型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
map Map

2.3.2 自定義別名

在SqlMapConfig.xml中進行以下配置:

<typeAliases>
    <!-- 單個別名定義 -->
    <typeAlias alias="user" type="com.kkb.mybatis.po.User"/>
    <!-- 批量別名定義,掃描整個包下的類,別名爲類名(首字母大寫或小寫均可以) -->
    <package name="com.kkb.mybatis.po"/>
</typeAliases>

2.4 mappers標籤

<mapper resource=""/>

使用相對於類路徑的資源

如:

<mapper resource="sqlmap/User.xml" />

<mapper url="">

使用絕對路徑加載資源

如:

<mapper url="file://d:/sqlmap/User.xml" />

<mapper class=""/>

使用mapper接口類路徑,加載映射文件。

如:

<mapper class="com.kkb.mybatis.mapper.UserMapper"/>

注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。

<package name=""/>

註冊指定包下的全部mapper接口,來加載映射文件。

如:

<package name="com.kkb.mybatis.mapper"/>

注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。

3. 輸入映射和輸出映射

3.1 parameterType(輸入類型)

parameterType屬性能夠映射的輸入參數Java類型有:簡單類型、POJO類型、Map類型、List類型(數組)

  • Map類型和POJO類型的用法相似,這裏只講POJO類型的相關配置。
  • List類型在動態SQL部分進行講解。

傳遞簡單類型

參考《Mybatis基礎》(在個人主頁內查找)中用戶查詢的案例。

傳遞pojo對象

參考《Mybatis基礎》(在個人主頁內查找)中的添加用戶的案例。

傳遞pojo包裝對象

包裝對象:pojo類中嵌套pojo。

需求

經過包裝POJO傳遞參數,完成用戶查詢。

QueryVO

定義包裝對象QueryVO

public class QueryVO {
     private User user;
}
SQL語句
SELECT * FROM user where username like '%小明%'
Mapper文件
<!-- 使用包裝類型查詢用戶 
        使用ognl從對象中取屬性值,若是是包裝對象可使用.操做符來取內容部的屬性
    -->
    <select id="findUserList" parameterType="queryVo" resultType="user">
        SELECT * FROM user where username like '%${user.username}%'
    </select>
Mapper接口
/**
 * 用戶管理mapper
 */
public interface UserMapper {
     //綜合查詢用戶列表
    public List<User> findUserList(QueryVo queryVo)throws Exception; 
}
測試方法

在UserMapperTest測試類中,添加如下測試代碼:

@Test
    public void testFindUserList() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //得到mapper的代理對象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //建立QueryVo對象
        QueryVo queryVo = new QueryVo();
        //建立user對象
        User user = new User();
        user.setUsername("小明");

        queryVo.setUser(user);
        //根據queryvo查詢用戶
        List<User> list = userMapper.findUserList(queryVo);
        System.out.println(list);
        sqlSession.close();
    }

3.2 resultType(輸出類型)

resultType屬性能夠映射的java類型有:簡單類型、POJO類型、Map類型

不過Map類型和POJO類型的使用狀況相似,因此只需講解POJO類型便可。

3.2.1 使用要求

使用resultType進行輸出映射時,要求sql語句中查詢的列名和要映射的pojo的屬性名一致。

3.2.2 映射簡單類型

案例需求

查詢用戶記錄總數。

Mapper映射文件
<!-- 獲取用戶列表總數 -->
    <select id="findUserCount" resultType="int">
       select count(1) from user
    </select>
Mapper接口
//查詢用戶總數
    public int  findUserCount() throws Exception;
測試代碼

在UserMapperTest測試類中,添加如下測試代碼:

@Test
    public void testFindUserCount() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //得到mapper的代理對象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        
         int count = userMapper.findUserCount(queryVo);
         System.out.println(count);

        sqlSession.close();
    }

注意:輸出簡單類型必須查詢出來的結果集只有一列。

3.2.3 映射pojo對象

注意:無論是單個POJO仍是POJO集合,在使用resultType完成映射時,用法同樣。

參考《Mybatis基礎》(在個人主頁內查找)中根據用戶ID查詢用戶信息和根據名稱模糊查詢用戶列表的案例

4. resultMap

4.1 使用要求

若是sql查詢列名和pojo的屬性名能夠不一致,經過resultMap將列名和屬性名做一個對應關係,最終將查詢結果映射到指定的pojo對象中。

注意:resultType底層也是經過resultMap完成映射的。

4.2 需求

將如下sql的查詢結果進行映射:

SELECT id id_,username username_,birthday birthday_ FROM user

4.3 Mapper接口

// resultMap入門
public List<User> findUserListResultMap() throws Exception;

4.4 Mapper映射文件

因爲sql查詢列名和User類屬性名不一致,因此不能使用resultType進行結構映射。

須要定義一個resultMap將sql查詢列名和User類的屬性名對應起來,完成結果映射。

<!-- 定義resultMap:將查詢的列名和映射的pojo的屬性名作一個對應關係 -->
    <!-- 
        type:指定查詢結果要映射的pojo的類型
        id:指定resultMap的惟一標示
     -->
    <resultMap type="user" id="userListResultMap">
        <!-- 
        id標籤:映射查詢結果的惟一列(主鍵列)
            column:查詢sql的列名
            property:映射結果的屬性名
        -->
        <id column="id_" property="id"/>
        <!-- result標籤:映射查詢結果的普通列 -->
        <result column="username_" property="username"/>
        <result column="birthday_" property="birthday"/>
    </resultMap>

    <!-- resultMap入門 -->
    <select id="findUserListResultMap" resultMap="userListResultMap">
        SELECT id id_,username username_,birthday birthday_ FROM user
    </select>
  • <id/>:表示查詢結果集的惟一標識,很是重要。若是是多個字段爲複合惟一約束則定義多個<id />

    • Property:表示User類的屬性。
    • Column:表示sql查詢出來的字段名。
    • Column和property放在一起表示將sql查詢出來的字段映射到指定的pojo類屬性上。
  • <result/>:普通結果,即pojo的屬性。
相關文章
相關標籤/搜索