rodert教你學(xué)MyBatis--實(shí)戰(zhàn)這一篇就夠了

歡迎大家前來(lái)白嫖PDF坷随。下圖回復(fù):666

本教程致力于最實(shí)用mybatis教程峦萎,個(gè)別圖片粘貼有丟失饮亏,還有來(lái)領(lǐng)取原版。

image.png

[toc]

前言

聲明:參考來(lái)源互聯(lián)網(wǎng)忠藤,有任何爭(zhēng)議可以留言挟伙。站在前人的肩上,我們才能看的更遠(yuǎn)熄驼。

本教程純手打像寒,致力于最實(shí)用教程烘豹,不需要什么獎(jiǎng)勵(lì)瓜贾,只希望多多轉(zhuǎn)發(fā)支持诺祸。
歡迎來(lái)我公眾號(hào),希望可以結(jié)識(shí)你祭芦,也可以催更筷笨,微信搜索:JavaPub

有任何問題都可以來(lái)談?wù)劊饶闩叮?/p>

[圖片上傳失敗...(image-7cdcdc-1588246105620)]

對(duì)mybatis有一定了解的龟劲,可以直接跳過前面基礎(chǔ)引入部分胃夏。

1,什么是Mybatis之JDBC攻城獅

1,1昌跌,使用idea構(gòu)建maven工程


1仰禀,2,引入mysql依賴包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.32</version>
</dependency>

1蚕愤,3答恶,準(zhǔn)備數(shù)據(jù)

  • 創(chuàng)建數(shù)據(jù)庫(kù):

create database mydatabase;

  • 創(chuàng)建表:
DROP TABLE IF EXISTS tb_user;
CREATE TABLE tb_user (
id char(32) NOT NULL,
user_name varchar(32) DEFAULT NULL,
password varchar(32) DEFAULT NULL,
name varchar(32) DEFAULT NULL,
age int(10) DEFAULT NULL,
sex int(2) DEFAULT NULL,
birthday date DEFAULT NULL,
created datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 插入數(shù)據(jù)
INSERT INTO mydatabase.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘zpc’, ‘123456’, ‘小明’, ‘22’, ‘1’, ‘1990-09-02’, sysdate(), sysdate());
INSERT INTO mydatabase.tb_user ( userName, password, name, age, sex, birthday, created, updated) VALUES ( ‘hj’, ‘123456’, ‘靜靜’, ‘22’, ‘1’, ‘1993-09-05’, sysdate(), sysdate());

1,4,jdbc代碼回顧

  • JDBCTest.class

7步操作數(shù)據(jù)庫(kù)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * @author Evan
 */
public class JDBCTest {
    public static void main(String[] args) throws Exception {
        Connection connection = null;
        PreparedStatement prepareStatement = null;
        ResultSet rs = null;

        try {
            // 1,加載驅(qū)動(dòng)
            Class.forName("com.mysql.jdbc.Driver");
            // 2,獲取連接
            String url = "jdbc:mysql://127.0.0.1:3306/mydatabase";
            String user = "root";
            String password = "123456";
            connection = DriverManager.getConnection(url, user, password);
            // 3,獲取statement萍诱,preparedStatement
            String sql = "select * from tb_user where id=?";
            prepareStatement = connection.prepareStatement(sql);
            // 4,設(shè)置參數(shù)
            prepareStatement.setLong(1, 1l);
            // 5,執(zhí)行查詢
            rs = prepareStatement.executeQuery();
            // 6,處理結(jié)果集
            while (rs.next()) {
                System.out.println(rs.getString("userName"));
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
                System.out.println(rs.getDate("birthday"));
            }
        } finally {
            // 7,關(guān)閉連接悬嗓,釋放資源
            if (rs != null) {
                rs.close();
            }
            if (prepareStatement != null) {
                prepareStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }
}

1,5裕坊,jdbc缺點(diǎn)分析

[圖片上傳失敗...(image-883f0f-1588246105620)]

4包竹,MyBatis介紹

官方文檔 http://www.mybatis.org/mybatis-3/getting-started.html

3,MyBatis整體架構(gòu)

[圖片上傳失敗...(image-2e5adf-1588246105620)]

4籍凝,快速入門(quick start)

4周瞎,1,引入依賴(pom.xml)

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
</dependency>

4饵蒂,2声诸,全局配置文件(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根標(biāo)簽 -->
<configuration>
<!--<properties>-->
<!--    <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!--    <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/>-->
<!--    <property name="username" value="root"/>-->
<!--    <property name="password" value="123456"/>-->
<!--</properties>-->

   <!-- 環(huán)境,可以配置多個(gè)苹享,default:指定采用哪個(gè)環(huán)境 -->
   <environments default="test">
      <!-- id:唯一標(biāo)識(shí) -->
      <environment id="test">
         <!-- 事務(wù)管理器双絮,JDBC類型的事務(wù)管理器 -->
         <transactionManager type="JDBC" />
         <!-- 數(shù)據(jù)源,池類型的數(shù)據(jù)源 -->
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis-110" />
            <property name="username" value="root" />
            <property name="password" value="123456" />
         </dataSource>
      </environment>
      <environment id="development">
         <!-- 事務(wù)管理器得问,JDBC類型的事務(wù)管理器 -->
         <transactionManager type="JDBC" />
         <!-- 數(shù)據(jù)源囤攀,池類型的數(shù)據(jù)源 -->
         <dataSource type="POOLED">
            <property name="driver" value="${driver}" /> <!-- 配置了properties,所以可以直接引用 -->
            <property name="url" value="${url}" />
            <property name="username" value="${username}" />
            <property name="password" value="${password}" />
         </dataSource>
      </environment>
   </environments>
</configuration>

4,3宫纬,配置Map.xml(MyMapper.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">
<!-- mapper:根標(biāo)簽焚挠,namespace:命名空間,隨便寫漓骚,一般保證命名空間唯一 -->
<mapper namespace="MyMapper">
   <!-- statement蝌衔,內(nèi)容:sql語(yǔ)句榛泛。id:唯一標(biāo)識(shí),隨便寫噩斟,在同一個(gè)命名空間下保持唯一
      resultType:sql語(yǔ)句查詢結(jié)果集的封裝類型,tb_user即為數(shù)據(jù)庫(kù)中的表名
    -->
   <select id="selectUser" resultType="com.zpc.mybatis.User">
      select * from tb_user where id = #{id}
   </select>
</mapper>

4曹锨,4,修改全局配置文件(mybatis-config.xml)

加入MyMapper.xml配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根標(biāo)簽 -->
<configuration>
   <!-- 環(huán)境剃允,可以配置多個(gè)沛简,default:指定采用哪個(gè)環(huán)境 -->
   <environments default="test">
      <!-- id:唯一標(biāo)識(shí) -->
      <environment id="test">
         <!-- 事務(wù)管理器,JDBC類型的事務(wù)管理器 -->
         <transactionManager type="JDBC" />
         <!-- 數(shù)據(jù)源斥废,池類型的數(shù)據(jù)源 -->
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mydatabase" />
            <property name="username" value="root" />
            <property name="password" value="123456" />
         </dataSource>
      </environment>
   </environments>
   <mappers>
     <mapper resource="mappers/MyMapper.xml" />
   </mappers>
</configuration>

4椒楣,5,構(gòu)建SqlSessionFactory(MybatisTest.java)

    // 指定全局配置文件
    String resource = "mybatis-config.xml";
    // 讀取配置文件
    InputStream inputStream = Resources.getResourceAsStream(resource);
    // 構(gòu)建sqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

4,6牡肉,打開sqlSession回話捧灰,并執(zhí)行sql(MyBatisTest.xml)

        // 獲取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 操作CRUD,第一個(gè)參數(shù):指定statement统锤,規(guī)則:命名空間+“.”+statementId
        // 第二個(gè)參數(shù):指定傳入sql的參數(shù):這里是用戶id
        User user = sqlSession.selectOne("MyMapper.selectUser", 1);
        System.out.println(user);
  • 完整代碼

MyBatisTest.java

import com.zpc.test.pojo.User;
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 java.io.InputStream;

public class MybatisTest {
   public static void main(String[] args) throws Exception {
      // 指定全局配置文件
      String resource = "mybatis-config.xml";
      // 讀取配置文件
      InputStream inputStream = Resources.getResourceAsStream(resource);
      // 構(gòu)建sqlSessionFactory
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      // 獲取sqlSession
      SqlSession sqlSession = sqlSessionFactory.openSession();
      try {
         // 操作CRUD毛俏,第一個(gè)參數(shù):指定statement,規(guī)則:命名空間+“.”+statementId
         // 第二個(gè)參數(shù):指定傳入sql的參數(shù):這里是用戶id
         User user = sqlSession.selectOne("MyMapper.selectUser", 1);
         System.out.println(user);
      } finally {
         sqlSession.close();
      }
   }
}

User.java

import java.text.SimpleDateFormat;
import java.util.Date;

public class User {
    private String id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private Integer sex;
    private Date birthday;
    private String created;
    private String updated;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getCreated() {
        return created;
    }

    public void setCreated(String created) {
        this.created = created;
    }

    public String getUpdated() {
        return updated;
    }

    public void setUpdated(String updated) {
        this.updated = updated;
    }
}

4,7跪另,目錄結(jié)構(gòu)

[圖片上傳失敗...(image-bcec7-1588246105620)]

5拧抖,分析

5,1,日志

5,2免绿,MyBatis使用步驟總結(jié)

1)配置mybatis-config.xml 全局的配置文件 (1唧席、數(shù)據(jù)源,2嘲驾、外部的mapper)

2)創(chuàng)建SqlSessionFactory

3)通過SqlSessionFactory創(chuàng)建SqlSession對(duì)象

4)通過SqlSession操作數(shù)據(jù)庫(kù) CRUD

5)調(diào)用session.commit()提交事務(wù)

6)調(diào)用session.close()關(guān)閉會(huì)話

6淌哟,完整增刪查改操作(CURD)

6,1辽故,創(chuàng)建USerDao.java接口

import com.zpc.mybatis.pojo.User;
import java.util.List;

public interface UserDao {

    /**
     * 根據(jù)id查詢用戶信息
     *
     * @param id
     * @return
     */
    public User queryUserById(String id);

    /**
     * 查詢所有用戶信息
     *
     * @return
     */
    public List<User> queryUserAll();

    /**
     * 新增用戶
     *
     * @param user
     */
    public void insertUser(User user);

    /**
     * 更新用戶信息
     *
     * @param user
     */
    public void updateUser(User user);

    /**
     * 根據(jù)id刪除用戶信息
     *
     * @param id
     */
    public void deleteUser(String id);
}

6,2,創(chuàng)建UserDaoImpl.java

import com.zpc.mybatis.dao.UserDao;
import com.zpc.mybatis.pojo.User;
import org.apache.ibatis.session.SqlSession;
import java.util.List;

public class UserDaoImpl implements UserDao {
    public SqlSession sqlSession;

    public UserDaoImpl(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public User queryUserById(String id) {
        return this.sqlSession.selectOne("UserDao.queryUserById", id);
    }

    @Override
    public List<User> queryUserAll() {
        return this.sqlSession.selectList("UserDao.queryUserAll");
    }

    @Override
    public void insertUser(User user) {
        this.sqlSession.insert("UserDao.insertUser", user);
    }

    @Override
    public void updateUser(User user) {
        this.sqlSession.update("UserDao.updateUser", user);
    }

    @Override
    public void deleteUser(String id) {
        this.sqlSession.delete("UserDao.deleteUser", id);
    }

}

6,3徒仓,編寫UserDao對(duì)應(yīng)Mapper(UserDaoMapper.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">
<!-- mapper:根標(biāo)簽,namespace:命名空間誊垢,隨便寫掉弛,一般保證命名空間唯一 -->
<mapper namespace="UserDao">
    <!-- statement,內(nèi)容:sql語(yǔ)句喂走。id:唯一標(biāo)識(shí)殃饿,隨便寫,在同一個(gè)命名空間下保持唯一
       resultType:sql語(yǔ)句查詢結(jié)果集的封裝類型,tb_user即為數(shù)據(jù)庫(kù)中的表
     -->
    <!--<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">-->
    <!--select * from tb_user where id = #{id}-->
    <!--</select>-->

    <!--使用別名-->
    <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">
      select
       tuser.id as id,
       tuser.user_name as userName,
       tuser.password as password,
       tuser.name as name,
       tuser.age as age,
       tuser.birthday as birthday,
       tuser.sex as sex,
       tuser.created as created,
       tuser.updated as updated
       from
       tb_user tuser
       where tuser.id = #{id};
   </select>

    <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user;
    </select>

    <!--插入數(shù)據(jù)-->
    <insert id="insertUser" parameterType="com.zpc.mybatis.pojo.User">
        INSERT INTO tb_user (
        user_name,
        password,
        name,
        age,
        sex,
        birthday,
        created,
        updated
        )
        VALUES
        (
        #{userName},
        #{password},
        #{name},
        #{age},
        #{sex},
        #{birthday},
        now(),
        now()
        );
    </insert>

    <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User">
        UPDATE tb_user
        <trim prefix="set" suffixOverrides=",">
            <if test="userName!=null">user_name = #{userName},</if>
            <if test="password!=null">password = #{password},</if>
            <if test="name!=null">name = #{name},</if>
            <if test="age!=null">age = #{age},</if>
            <if test="sex!=null">sex = #{sex},</if>
            <if test="birthday!=null">birthday = #{birthday},</if>
            updated = now(),
        </trim>
        WHERE
        (id = #{id});
    </update>

    <delete id="deleteUser">
        delete from tb_user where id=#{id}
    </delete>
</mapper>
  • 添加配置(mybatis-config.xml)
<mappers>
    <mapper resource="mappers/MyMapper.xml"/>
    <mapper resource="mappers/UserDaoMapper.xml"/>
</mappers>

6,4,添加UserDao測(cè)試用例

pom.xml文件添加junit依賴

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

UserDao.java芋肠,按住Alt+Enter,選擇create test

[圖片上傳失敗...(image-b1a329-1588246105620)]

6.5.編寫UserDao的測(cè)試用例

import com.zpc.mybatis.dao.UserDao;
import com.zpc.mybatis.dao.impl.UserDaoImpl;
import com.zpc.mybatis.pojo.User;
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 java.io.InputStream;
import java.util.Date;
import java.util.List;

public class UserDaoTest {

    public UserDao userDao;
    public SqlSession sqlSession;

    @Before
    public void setUp() throws Exception {
        // mybatis-config.xml
        String resource = "mybatis-config.xml";
        // 讀取配置文件
        InputStream is = Resources.getResourceAsStream(resource);
        // 構(gòu)建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        // 獲取sqlSession
        sqlSession = sqlSessionFactory.openSession();
        this.userDao = new UserDaoImpl(sqlSession);
    }

    @Test
    public void queryUserById() throws Exception {
        System.out.println(this.userDao.queryUserById("1"));
    }

    @Test
    public void queryUserAll() throws Exception {
        List<User> userList = this.userDao.queryUserAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void insertUser() throws Exception {
        User user = new User();
        user.setAge(16);
        user.setBirthday(new Date("1990/09/02"));
        user.setName("大鵬");
        user.setPassword("123456");
        user.setSex(1);
        user.setUserName("evan");
        this.userDao.insertUser(user);
        this.sqlSession.commit();
    }

    @Test
    public void updateUser() throws Exception {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("靜鵬");
        user.setPassword("654321");
        user.setSex(1);
        user.setUserName("evanjin");
        user.setId("1");
        this.userDao.updateUser(user);
        this.sqlSession.commit();
    }

    @Test
    public void deleteUser() throws Exception {
        this.userDao.deleteUser("4");
        this.sqlSession.commit();
    }

}

6.6.目錄結(jié)構(gòu)

[圖片上傳失敗...(image-41386b-1588246105620)]

6.7.解決數(shù)據(jù)庫(kù)字段名和實(shí)體類屬性名不一致的問題

查詢數(shù)據(jù)的時(shí)候乎芳,發(fā)現(xiàn)查不到userName的信息,
User{id=‘2’, userName=‘null’, password=‘123456’, name=‘靜靜’, age=22, sex=0, birthday=‘1993-09-05’, created=‘2018-06-30 18:22:28.0’, updated=‘2018-06-30 18:22:28.0’}
原因:數(shù)據(jù)庫(kù)的字段名是user_name,POJO中的屬性名字是userName
兩端不一致奈惑,造成mybatis無(wú)法填充對(duì)應(yīng)的字段信息吭净。修改方法:在sql語(yǔ)句中使用別名。

  • 解決方案1:在sql語(yǔ)句中使用別名:
<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">
   select
    tuser.id as id,
    tuser.user_name as userName,
    tuser.password as password,
    tuser.name as name,
    tuser.age as age,
    tuser.birthday as birthday,
    tuser.sex as sex,
    tuser.created as created,
    tuser.updated as updated
    from
    tb_user tuser
    where tuser.id = #{id};
</select>
  • 解決方案2: 參考后面的resultMap –mapper具體的配置的時(shí)候

  • 解決方案3:參考駝峰匹配 — mybatis-config.xml 的時(shí)候

7. 動(dòng)態(tài)代理Mapper實(shí)現(xiàn)類

7.1.思考上述CRUD中的問題

  1. 接口 -> 實(shí)現(xiàn)類 -> mapping.xml
  2. 實(shí)現(xiàn)類中肴甸,使用mybatis的方式非常相似
  3. xml的sql statement 硬編碼到Java代碼中
  • 思考:能否直接寫接口寂殉,不寫實(shí)現(xiàn)類。只編寫接口和Mapping.xml即可雷滋?
  • 因?yàn)樵賒ao(mapper)的實(shí)現(xiàn)類中對(duì)sqlsession的使用方式很類似不撑。因此mybatis提供了接口的動(dòng)態(tài)代理文兢。

7晤斩,2,使用動(dòng)態(tài)代理改造CRUD

  • 修改測(cè)試用例的setUp方法

[圖片上傳失敗...(image-a4602c-1588246105620)]

  • 執(zhí)行queryUserAll()方法

[圖片上傳失敗...(image-d3e6c8-1588246105620)]

org.apache.ibatis.binding.BindingException: Type interface com.zpc.mybatis.dao.UserDao is not known to the MapperRegistry.
    at org.apache.ibatis.binding.MapperRegistry.getMapper(MapperRegistry.java:47)
    at org.apache.ibatis.session.Configuration.getMapper(Configuration.java:655)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.getMapper(DefaultSqlSession.java:222)
at com.zpc.mybatis.test.UserDaoTest.setUp(UserDaoTest.java:32)
  • 分析原因姆坚,在UserMapper.xml中配置接口的全路徑
    mapper.xml namespace
    如果希望使用mybatis通過的動(dòng)態(tài)代理的接口澳泵,就需要namespace中的值,和需要對(duì)應(yīng)的Mapper(dao)接口的全路徑一致兼呵。Mapper中Namespace的定義本身是沒有限制的兔辅,只要不重復(fù)即可,但如果使用Mybatis的DAO接口動(dòng)態(tài)代理击喂,則namespace必須為DAO接口的全路徑维苔,例如:com.zpc.mybatis.dao.UserDao

<mapper namespace="com.zpc.mybatis.dao.UserDao">

7.3.完整的例子

  1. 創(chuàng)建UserMapper接口(對(duì)應(yīng)原UserDao)
public interface UserMapper {
   
   /**
    * 登錄(直接使用注解指定傳入?yún)?shù)名稱)
    * @param userName
    * @param password
    * @return
    */
   public User login(@Param("userName") String userName, @Param("password") String password);
   
   /**
    * 根據(jù)表名查詢用戶信息(直接使用注解指定傳入?yún)?shù)名稱)
    * @param tableName
    * @return
    */
   public List<User> queryUserByTableName(@Param("tableName") String tableName);
   
   /**
    * 根據(jù)Id查詢用戶信息
    * @param id
    * @return
    */
   public User queryUserById(Long id);
   
   /**
    * 查詢所有用戶信息
    * @return
    */
   public List<User> queryUserAll();
   
   /**
    * 新增用戶信息
    * @param user
    */
   public void insertUser(User user);
   
   /**
    * 根據(jù)id更新用戶信息
    * @param user
    */
   public void updateUser(User user);
   
   /**
    * 根據(jù)id刪除用戶信息
    * @param id
    */
   public void deleteUserById(Long id);
}
  1. 創(chuàng)建Usermapper.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">
<!-- mapper:根標(biāo)簽,namespace:命名空間懂昂,隨便寫介时,一般保證命名空間唯一 ,為了使用接口動(dòng)態(tài)代理凌彬,這里必須是接口的全路徑名-->
<mapper namespace="com.zpc.mybatis.dao.UserMapper">
    <!--
       1.#{},預(yù)編譯的方式preparedstatement沸柔,使用占位符替換,防止sql注入铲敛,一個(gè)參數(shù)的時(shí)候褐澎,任意參數(shù)名可以接收
       2.${},普通的Statement,字符串直接拼接伐蒋,不可以防止sql注入工三,一個(gè)參數(shù)的時(shí)候,必須使用${value}接收參數(shù)
     -->
    <select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
        select * from ${tableName}
    </select>

    <select id="login" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where user_name = #{userName} and password = #{password}
    </select>

    <!-- statement先鱼,內(nèi)容:sql語(yǔ)句俭正。
       id:唯一標(biāo)識(shí),隨便寫型型,在同一個(gè)命名空間下保持唯一段审,使用動(dòng)態(tài)代理之后要求和方法名保持一致
       resultType:sql語(yǔ)句查詢結(jié)果集的封裝類型,使用動(dòng)態(tài)代理之后和方法的返回類型一致;resultMap:二選一
       parameterType:參數(shù)的類型寺枉,使用動(dòng)態(tài)代理之后和方法的參數(shù)類型一致
     -->
    <select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user where id = #{id}
    </select>
    <select id="queryUserAll" resultType="com.zpc.mybatis.pojo.User">
        select * from tb_user
    </select>
    <!-- 新增的Statement
       id:唯一標(biāo)識(shí)抑淫,隨便寫,在同一個(gè)命名空間下保持唯一姥闪,使用動(dòng)態(tài)代理之后要求和方法名保持一致
       parameterType:參數(shù)的類型始苇,使用動(dòng)態(tài)代理之后和方法的參數(shù)類型一致
       useGeneratedKeys:開啟主鍵回寫
       keyColumn:指定數(shù)據(jù)庫(kù)的主鍵
       keyProperty:主鍵對(duì)應(yīng)的pojo屬性名
     -->
    <insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
            parameterType="com.zpc.mybatis.pojo.User">
        INSERT INTO tb_user (
        id,
        user_name,
        password,
        name,
        age,
        sex,
        birthday,
        created,
        updated
        )
        VALUES
        (
        null,
        #{userName},
        #{password},
        #{name},
        #{age},
        #{sex},
        #{birthday},
        NOW(),
        NOW()
        );
    </insert>
    <!-- 
       更新的statement
       id:唯一標(biāo)識(shí),隨便寫筐喳,在同一個(gè)命名空間下保持唯一催式,使用動(dòng)態(tài)代理之后要求和方法名保持一致
       parameterType:參數(shù)的類型,使用動(dòng)態(tài)代理之后和方法的參數(shù)類型一致
     -->
    <update id="updateUser" parameterType="com.zpc.mybatis.pojo.User">
        UPDATE tb_user
        <trim prefix="set" suffixOverrides=",">
            <if test="userName!=null">user_name = #{userName},</if>
            <if test="password!=null">password = #{password},</if>
            <if test="name!=null">name = #{name},</if>
            <if test="age!=null">age = #{age},</if>
            <if test="sex!=null">sex = #{sex},</if>
            <if test="birthday!=null">birthday = #{birthday},</if>
            updated = now(),
        </trim>
        WHERE
        (id = #{id});
    </update>
    <!-- 
       刪除的statement
       id:唯一標(biāo)識(shí)避归,隨便寫荣月,在同一個(gè)命名空間下保持唯一,使用動(dòng)態(tài)代理之后要求和方法名保持一致
       parameterType:參數(shù)的類型梳毙,使用動(dòng)態(tài)代理之后和方法的參數(shù)類型一致
     -->
    <delete id="deleteUserById" parameterType="java.lang.String">
        delete from tb_user where id=#{id}
    </delete>
</mapper>
  1. 全局配置文件mybatis-config.xml引入U(xiǎn)serMapper.xml
<mappers>
    <mapper resource="mappers/MyMapper.xml"/>
    <mapper resource="mappers/UserDaoMapper.xml"/>
    <mapper resource="mappers/UserMapper.xml"/>
</mappers>
  1. 創(chuàng)建UserMapper測(cè)試用例
import com.zpc.mybatis.dao.UserMapper;
import com.zpc.mybatis.pojo.User;
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 java.io.InputStream;
import java.util.Date;
import java.util.List;

public class UserMapperTest {

    public UserMapper userMapper;

    @Before
    public void setUp() throws Exception {
        // 指定配置文件
        String resource = "mybatis-config.xml";
        // 讀取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 構(gòu)建sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 獲取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        // 1. 映射文件的命名空間(namespace)必須是mapper接口的全路徑
        // 2. 映射文件的statement的id必須和mapper接口的方法名保持一致
        // 3. Statement的resultType必須和mapper接口方法的返回類型一致
        // 4. statement的parameterType必須和mapper接口方法的參數(shù)類型一致(不一定)
        this.userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @Test
    public void testQueryUserByTableName() {
        List<User> userList = this.userMapper.queryUserByTableName("tb_user");
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void testLogin() {
        System.out.println(this.userMapper.login("hj", "123456"));
    }

    @Test
    public void testQueryUserById() {
        System.out.println(this.userMapper.queryUserById("1"));
    }

    @Test
    public void testQueryUserAll() {
        List<User> userList = this.userMapper.queryUserAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void testInsertUser() {
        User user = new User();
        user.setAge(20);
        user.setBirthday(new Date());
        user.setName("大神");
        user.setPassword("123456");
        user.setSex(2);
        user.setUserName("bigGod222");
        this.userMapper.insertUser(user);
        System.out.println(user.getId());
    }

    @Test
    public void testUpdateUser() {
        User user = new User();
        user.setBirthday(new Date());
        user.setName("靜靜");
        user.setPassword("123456");
        user.setSex(0);
        user.setUserName("Jinjin");
        user.setId("1");
        this.userMapper.updateUser(user);
    }

    @Test
    public void testDeleteUserById() {
        this.userMapper.deleteUserById("1");
    }
}
  • 目錄結(jié)構(gòu):

[圖片上傳失敗...(image-c58161-1588246105620)]

7,4哺窄,動(dòng)態(tài)代理總結(jié)

使用mapper接口不用寫接口實(shí)現(xiàn)類即可完成數(shù)據(jù)庫(kù)操作,使用非常方便账锹,也是官方推薦的使用方式萌业。

  1. Mapper的namespace必須和mapper接口的全路徑一致。
  2. Mapper接口的方法名必須和sql定義的id一致奸柬。
  3. Mapper接口中方法的輸入?yún)?shù)類型必須和sql定義的parameterType一致生年。(這句需要再琢磨)
  4. Mapper接口中方法的輸出參數(shù)類型必須和sql定義的resultType一致。

8廓奕,mybatis-config.xml詳解

mybatis-config.xml講究嚴(yán)格的順序抱婉,具體順序遵循文檔的順序。

[圖片上傳失敗...(image-8da5cf-1588246105620)]

8,1懂从,properties屬性讀取外部資源

properties配置的屬性都是可外部配置且可動(dòng)態(tài)替換的授段,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來(lái)傳遞番甩。例如:

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

然后其中的屬性就可以在整個(gè)配置文件中被用來(lái)替換需要?jiǎng)討B(tài)配置的屬性值侵贵。比如:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

這個(gè)例子中的 username 和 password 將會(huì)由 properties 元素中設(shè)置的相應(yīng)值來(lái)替換。 driver 和 url 屬性將會(huì)由 config.properties 文件中對(duì)應(yīng)的值來(lái)替換缘薛。這樣就為配置提供了諸多靈活選擇窍育。

  • 屬性也可以被傳遞到 SqlSessionFactoryBuilder.build()方法中。例如:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
// ... or ...
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);

如果屬性在不只一個(gè)地方進(jìn)行了配置宴胧,那么 MyBatis 將按照下面的順序來(lái)加載:

  1. 在 properties 元素體內(nèi)指定的屬性首先被讀取漱抓。
  2. 然后根據(jù) properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據(jù) url 屬性指定的路徑讀取屬性文件,并覆蓋已讀取的同名屬性恕齐。
  3. 最后讀取作為方法參數(shù)傳遞的屬性乞娄,并覆蓋已讀取的同名屬性。

因此,通過方法參數(shù)傳遞的屬性具有最高優(yōu)先級(jí)仪或,resource/url 屬性中指定的配置文件次之确镊,最低優(yōu)先級(jí)的是 properties 屬性中指定的屬性。

8,2,settings設(shè)置

[圖片上傳失敗...(image-6b5978-1588246105620)]

  • 開啟駝峰匹配:
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

8,3,typeAliases(別名)

類型別名是為 Java 類型命名的一個(gè)短的名字范删。它只和 XML 配置有關(guān)蕾域,存在的意義僅在于用來(lái)減少類完全限定名的冗余。

<typeAliases>
    <typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>
</typeAliases>

缺點(diǎn):每個(gè)pojo類都要去配置到旦。
解決方案:使用掃描包旨巷,掃描指定包下的所有類,掃描之后的別名就是類名(不區(qū)分大小寫)添忘,建議使用的時(shí)候和類名一致

<typeAliases>
    <!--type:實(shí)體類的全路徑采呐。alias:別名,通常首字母大寫-->
    <!--<typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>-->
    <package name="com.zpc.mybatis.pojo"/>
</typeAliases>

Mybatis已經(jīng)為普通的 Java 類型內(nèi)建了許多相應(yīng)的類型別名昔汉。它們都是大小寫不敏感的懈万。

[圖片上傳失敗...(image-5d1631-1588246105620)]

8,4,typeHandlers(類處理器)

無(wú)論是 MyBatis 在預(yù)處理語(yǔ)句(PreparedStatement)中設(shè)置一個(gè)參數(shù)時(shí),還是從結(jié)果集中取出一個(gè)值時(shí)靶病, 都會(huì)用類型處理器將獲取的值以合適的方式轉(zhuǎn)換成 Java 類型】谟瑁可以重寫類型處理器或創(chuàng)建你自己的類型處理器來(lái)處理不支持的或非標(biāo)準(zhǔn)的類型娄周。

8.5.plugins(插件)攔截器

MyBatis 允許你在已映射語(yǔ)句執(zhí)行過程中的某一點(diǎn)進(jìn)行攔截調(diào)用。默認(rèn)情況下沪停,MyBatis 允許使用插件來(lái)攔截的方法調(diào)用包括:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)

現(xiàn)在一些MyBatis 插件比如PageHelper都是基于這個(gè)原理煤辨,有時(shí)為了監(jiān)控sql執(zhí)行效率,也可以使用插件機(jī)制
原理:

[圖片上傳失敗...(image-baa253-1588246105620)]

// ExamplePlugin.java
@Intercepts({@Signature(
  type= Executor.class,
  method = "update",
  args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
  public Object intercept(Invocation invocation) throws Throwable {
    return invocation.proceed();
  }
  public Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }
  public void setProperties(Properties properties) {
  }
}

配置:

<!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins>

上面的插件將會(huì)攔截在 Executor 實(shí)例中所有的 “update” 方法調(diào)用木张, 這里的 Executor 是負(fù)責(zé)執(zhí)行低層映射語(yǔ)句的內(nèi)部對(duì)象众辨。

8.6.environments(環(huán)境)

MyBatis 可以配置成適應(yīng)多種環(huán)境,例如舷礼,開發(fā)鹃彻、測(cè)試和生產(chǎn)環(huán)境需要有不同的配置;
盡管可以配置多個(gè)環(huán)境妻献,每個(gè) SqlSessionFactory 實(shí)例只能選擇其一蛛株。
雖然,這種方式也可以做到很方便的分離多個(gè)環(huán)境育拨,但是實(shí)際使用場(chǎng)景下谨履,我們更多的是選擇使用spring來(lái)管理數(shù)據(jù)源,來(lái)做到環(huán)境的分離熬丧。

8.7.mappers

需要告訴 MyBatis 到哪里去找到 SQL 映射語(yǔ)句笋粟。即告訴 MyBatis 到哪里去找映射文件。你可以使用相對(duì)于類路徑的資源引用, 或完全限定資源定位符(包括 file:/// 的 URL)害捕,或類名和包名等唆香。例如:

<!-- 使用相對(duì)于類路徑的資源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

<!-- 使用映射器接口實(shí)現(xiàn)類的完全限定類名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

這里所謂的mapper接口路徑。實(shí)際上就是dao的接口路徑吨艇。在mybatis中躬它,通常把dao的包叫做mapper。類名东涡,也叫做mapper

  1. 定義一個(gè)接口冯吓。
  2. 在接口所在的包中定義mapper.xml,并且要求xml文件和interface的名稱要相同疮跑。
  3. 在mybatis-config.xml 中通過class路徑组贺,引入mapper(注解方式)。要求mapper.xml 中的名稱空間是類的接口的全路徑祖娘。

注解方式:

<mappers>
    <mapper resource="mappers/MyMapper.xml"/>
    <mapper resource="mappers/UserDaoMapper.xml"/>
    <!--注解方式可以使用如下配置方式-->
    <mapper class="com.zpc.mybatis.dao.UserMapper"/>
</mappers>

問題:

  1. mapper.xml 和 java文件沒有分離失尖。 之后的教程講述和spring整合之后解決。
  2. 需要一個(gè)一個(gè)的去加載mapper渐苏。

當(dāng)然也可以使用包掃描(必須使用注解方式掀潮,即在接口方法上使用注解琼富,如@Select("select * from tb_user ")):
缺點(diǎn):

  1. 如果包的路徑有很多菩颖?
  2. mapper.xml和mapper.java沒有分離。
  • spring整合的時(shí)候解決。

9.Mapper XML文件詳解

9.1.CRUD標(biāo)簽

9.1.1.select

select – 書寫查詢sql語(yǔ)句
select中的幾個(gè)屬性說(shuō)明:
id屬性:當(dāng)前名稱空間下的statement的唯一標(biāo)識(shí)。必須将鸵。要求id和mapper接口中的方法的名字一致挑胸。
resultType:將結(jié)果集映射為java的對(duì)象類型。必須(和 resultMap 二選一)
parameterType:傳入?yún)?shù)類型。可以省略

9.1.2.insert

insert 的幾個(gè)屬性說(shuō)明:
id:唯一標(biāo)識(shí)奄妨,隨便寫树枫,在同一個(gè)命名空間下保持唯一,使用動(dòng)態(tài)代理之后要求和方法名保持一致
parameterType:參數(shù)的類型,使用動(dòng)態(tài)代理之后和方法的參數(shù)類型一致
useGeneratedKeys:開啟主鍵回寫
keyColumn:指定數(shù)據(jù)庫(kù)的主鍵
keyProperty:主鍵對(duì)應(yīng)的pojo屬性名
標(biāo)簽內(nèi)部:具體的sql語(yǔ)句诬留。

9.1.3.update

id屬性:當(dāng)前名稱空間下的statement的唯一標(biāo)識(shí)(必須屬性)腺劣;
parameterType:傳入的參數(shù)類型涡上,可以省略耻警。
標(biāo)簽內(nèi)部:具體的sql語(yǔ)句。

9.1.4.delete

delete 的幾個(gè)屬性說(shuō)明:
id屬性:當(dāng)前名稱空間下的statement的唯一標(biāo)識(shí)(必須屬性);
parameterType:傳入的參數(shù)類型届垫,可以省略妄迁。
標(biāo)簽內(nèi)部:具體的sql語(yǔ)句。

9.2.#{}和${}

場(chǎng)景:數(shù)據(jù)庫(kù)有兩個(gè)一模一樣的表。歷史表,當(dāng)前表
查詢表中的信息峭判,有時(shí)候從歷史表中去查詢數(shù)據(jù)疗认,有時(shí)候需要去新的表去查詢數(shù)據(jù)扎拣。
希望使用1個(gè)方法來(lái)完成操作。

<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
    select * from #{tableName}
</select>

/**
 * 根據(jù)表名查詢用戶信息(直接使用注解指定傳入?yún)?shù)名稱)
 *
 * @param tableName
 * @return
 */
public List<User> queryUserByTableName(String tableName);

測(cè)試輸出:

有問題,報(bào)語(yǔ)法錯(cuò)誤:相當(dāng)于執(zhí)行了這樣一條sql:
select * from “tb_user”;
顯然表名多了引號(hào)晰甚。

  • 改正:
<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
    select * from ${tableName}
</select>

注意:

{} 只是替換俊鱼?,相當(dāng)于PreparedStatement使用占位符去替換參數(shù)嗓违,可以防止sql注入佳窑。

{} 是進(jìn)行字符串拼接瓣喊,相當(dāng)于sql語(yǔ)句中的Statement渣玲,使用字符串去拼接sql瑟押;可以是sql中的任一部分傳入到Statement中,不能防止sql注入木西。

使用{} 去取出參數(shù)值信息,需要使用{value}

{} 只是表示占位重绷,與參數(shù)的名字無(wú)關(guān)沸停,如果只有一個(gè)參數(shù),會(huì)自動(dòng)對(duì)應(yīng)昭卓。

推薦:

/**
 * 根據(jù)表名查詢用戶信息(直接使用注解指定傳入?yún)?shù)名稱)
 *
 * @param tableName
 * @return
 */
public List<User> queryUserByTableName(@Param("tableName") String tableName);

<select id="queryUserByTableName" resultType="com.zpc.mybatis.pojo.User">
    select * from ${tableName}
</select>

{}多個(gè)參數(shù)時(shí):

/**
 * 登錄(直接使用注解指定傳入?yún)?shù)名稱)
 *
 * @param userName
 * @param password
 * @return
 */
public User login( String userName, String password);

<select id="login" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user where user_name = #{userName} and password = #{password}
</select>

報(bào)錯(cuò):

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found. Available parameters are [0, 1, param1, param2]

解決方案一:

<select id="login" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user where user_name = #{0} and password = #{1}
</select>

解決方案二:

<select id="login" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user where user_name = #{param1} and password = #{param2}
</select>

最終解決方案:

/**
 * 登錄(直接使用注解指定傳入?yún)?shù)名稱)
 *
 * @param userName
 * @param password
 * @return
 */
public User login(@Param("userName") String userName, @Param("password") String password);

<select id="login" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user where user_name = #{userName} and password = #{password}
</select>

通常在方法的參數(shù)列表上加上一個(gè)注釋@Param(“xxxx”) 顯式指定參數(shù)的名字愤钾,然后通過{“xxxx”}或#{“xxxx”} sql語(yǔ)句動(dòng)態(tài)生成的時(shí)候,使用{};
sql語(yǔ)句中某個(gè)參數(shù)進(jìn)行占位的時(shí)候#{}

9.3.面試題(#候醒、$區(qū)別)

/**
 * #號(hào)
 * @param username1
 * @return
 */
User queryUserListByName1(@Param("username1") String username1);

/**
 * $號(hào)
 * @param username2
 * @return
 */
User queryUserListByName2(@Param("username2") String username2);

<select id="queryUserListByName1" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user WHERE user_name=#{username1}
</select>

<select id="queryUserListByName2" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user WHERE user_name='${username2}'//手動(dòng)加了引號(hào)
</select>

9.4.resultMap

[圖片上傳失敗...(image-738b49-1588246105621)]

[圖片上傳失敗...(image-ed1160-1588246105621)]

使用:
[圖片上傳失敗...(image-7fb649-1588246105621)]

9.5.sql片段

<sql id=””></sql>
<include refId=”” />

例如在UserMapper.xml中定義如下片段:

<sql id="commonSql">
                id,
            user_name,
            password,
            name,
            age,
            sex,
            birthday,
            created,
            updated 
</sql> 

則可以在UserMapper.xml中使用它:

<select id="queryUserById" resultMap="userResultMap">
    select <include refid="commonSql"></include> from tb_user where id = #{id}
</select>

<select id="queryUsersLikeUserName" resultType="User">
    select <include refid="commonSql"></include> from tb_user where user_name like "%"#{userName}"%"
</select>

Sql片段也可以定義在單獨(dú)的.xml文件中如:
定義CommonSQL.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">
<mapper namespace="CommonSQL">
    <sql id="commonSql">
        id,
            user_name,
            password,
            name,
            age,
            sex,
            birthday,
            created,
            updated 
    </sql>
</mapper>

使用:

    <select id="queryUserById" resultMap="userResultMap">
        select <include refid="CommonSQL.commonSql"></include> from tb_user where id = #{id}
    </select>
    
    <select id="queryUsersLikeUserName" resultType="User">
        select <include refid="CommonSQL.commonSql"></include> from tb_user where user_name like "%"#{userName}"%"
    </select>

當(dāng)然要完成這個(gè)功能還需要在全局配置文件mybatis-config.xml中引入該外部配置文件:

<mappers>
        <mapper resource="CommonSQL.xml"/>
        <!-- 開啟mapper接口的包掃描绰垂,基于class的配置方式 -->
        <package name="com.zpc.mybatis.mapper"/>
</mappers>

10.動(dòng)態(tài)sql

場(chǎng)景:查詢男性用戶,如果輸入了姓名火焰,按姓名模糊查詢
[圖片上傳失敗...(image-31de29-1588246105621)]

10.1.if

場(chǎng)景:查詢男性用戶,如果輸入了姓名胧沫,則按姓名查詢

定義接口:

/**
 * 查詢男性用戶昌简,如果輸入了姓名占业,則按姓名查詢
 * @param name
 * @return
 */
List<User> queryUserList(@Param("name") String name);

編寫mapper

<select id="queryUserList" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user WHERE sex=1
    <if test="name!=null and name.trim()!=''">
      and name like '%${name}%'
    </if>
</select>

測(cè)試:

@Test
public void testqueryUserList() {
    List<User> users = this.userMapper.queryUserList(null);
    for (User user : users) {
        System.out.println(user);
    }
}

10.2.choose when otherwise

場(chǎng)景:查詢男性用戶,如果輸入了姓名則按照姓名模糊查找纯赎,否則如果輸入了年齡則按照年齡查找谦疾,否則查找姓名為“鵬程”的用戶。

定義接口:

/**
 * 查詢男性用戶犬金,如果輸入了姓名則按照姓名模糊查找念恍,否則如果輸入了年齡則按照年齡查找,否則查找姓名為“鵬程”的用戶晚顷。
 * @param name
 * @param age
 * @return
 */
List<User> queryUserListByNameOrAge(@Param("name") String name,@Param("age") Integer age);

編寫mapper配置:

<select id="queryUserListByNameOrAge" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user WHERE sex=1
    <!--
    1.一旦有條件成立的when峰伙,后續(xù)的when則不會(huì)執(zhí)行
    2.當(dāng)所有的when都不執(zhí)行時(shí),才會(huì)執(zhí)行otherwise
    -->
    <choose>
        <when test="name!=null and name.trim()!=''">
            and name like '%${name}%'
        </when>
        <when test="age!=null">
            and age = #{age}
        </when>
        <otherwise>
            and name='鵬程'
        </otherwise>
    </choose>
</select>

測(cè)試:

@Test
public void queryUserListByNameOrAge() throws Exception {
    List<User> users = this.userMapper.queryUserListByNameOrAge(null, 16);
    for (User user : users) {
        System.out.println(user);
    }
}

10.3.where 和set

場(chǎng)景一:查詢所有用戶,如果輸入了姓名按照姓名進(jìn)行模糊查詢该默,如果輸入年齡瞳氓,按照年齡進(jìn)行查詢,如果兩者都輸入栓袖,兩個(gè)條件都要成立匣摘。

接口:

/**
 * 查詢所有用戶,如果輸入了姓名按照姓名進(jìn)行模糊查詢裹刮,如果輸入年齡音榜,按照年齡進(jìn)行查詢,如果兩者都輸入捧弃,兩個(gè)條件都要成立
 * @param name
 * @param age
 * @return
 */
List<User> queryUserListByNameAndAge(@Param("name") String name,@Param("age") Integer age);

配置:

<select id="queryUserListByNameAndAge" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user
    <!--如果多出一個(gè)and赠叼,會(huì)自動(dòng)去除,如果缺少and或者多出多個(gè)and則會(huì)報(bào)錯(cuò)-->
    <where>
        <if test="name!=null and name.trim()!=''">
            and name like '%${name}%'
        </if>
        <if test="age!=null">
            and age = #{age}
        </if>
    </where>
</select>

測(cè)試:

@Test
public void queryUserListByNameAndAge() throws Exception {
    List<User> users = this.userMapper.queryUserListByNameAndAge("鵬程", 20);
    for (User user : users) {
        System.out.println(user);
    }
}

場(chǎng)景二:修改用戶信息塔橡,如果參數(shù)user中的某個(gè)屬性為null梅割,則不修改。
接口:

/**
 * 根據(jù)id更新用戶信息
 *
 * @param user
 */
public void updateUser(User user);

配置:

<update id="updateUser" parameterType="com.zpc.mybatis.pojo.User">
    UPDATE tb_user
    <trim prefix="set" suffixOverrides=",">
        <if test="userName!=null">user_name = #{userName},</if>
        <if test="password!=null">password = #{password},</if>
        <if test="name!=null">name = #{name},</if>
        <if test="age!=null">age = #{age},</if>
        <if test="sex!=null">sex = #{sex},</if>
        <if test="birthday!=null">birthday = #{birthday},</if>
        updated = now(),
    </trim>
    WHERE
    (id = #{id});
</update>

測(cè)試:

@Test
public void testUpdateUser() {
    User user = new User();
    user.setBirthday(new Date());
    user.setName("靜靜");
    user.setPassword("123456");
    user.setSex(0);
    user.setUserName("Jinjin");
    user.setId("1");
    this.userMapper.updateUser(user);
}

10.4.foreach

場(chǎng)景:按照多個(gè)id查詢用戶信息

接口:

/**
 * 按多個(gè)Id查詢
 * @param ids
 * @return
 */
List<User> queryUserListByIds(@Param("ids") String[] ids);

配置:

<select id="queryUserListByIds" resultType="com.zpc.mybatis.pojo.User">
    select * from tb_user where id in
    <foreach collection="ids" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</select>

測(cè)試:

@Test
public void queryUserListByIds() throws Exception {
    List<User> users = this.userMapper.queryUserListByIds(new String[]{"1","2"});
    for (User user : users) {
        System.out.println(user);
    }
}

If:testognl表達(dá)式或者簡(jiǎn)單java代碼
Choose when otherwise—>相當(dāng)于if else if else
When test參考if
Where set 都有一定的糾錯(cuò)功能
Trim:prefix suffix prefixOverrides suffixOverrides
Foreach:collection item saparator open close

11.緩存

11.1.一級(jí)緩存

[圖片上傳失敗...(image-b1f84b-1588246105621)]

在mybatis中葛家,一級(jí)緩存默認(rèn)是開啟的户辞,并且一直無(wú)法關(guān)閉

一級(jí)緩存滿足條件:
1、同一個(gè)session中
2癞谒、相同的SQL和參數(shù)

測(cè)試:

@Test
public void testQueryUserById() {
    System.out.println(this.userMapper.queryUserById("1"));
    System.out.println(this.userMapper.queryUserById("1"));
}
2018-07-01 17:08:50,156 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2018-07-01 17:08:50,421 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057.
2018-07-01 17:08:50,423 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-07-01 17:08:50,476 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
2018-07-01 17:08:50,509 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}

使用:sqlSession.clearCache();可以強(qiáng)制清除緩存

測(cè)試:

@Test
public void testQueryUserById() {
    System.out.println(this.userMapper.queryUserById("1"));
    sqlSession.clearCache();
    System.out.println(this.userMapper.queryUserById("1"));
}

日志:

2018-07-01 17:10:51,065 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2018-07-01 17:10:51,359 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057.
2018-07-01 17:10:51,360 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-07-01 17:10:51,408 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
2018-07-01 17:10:51,437 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-07-01 17:10:51,438 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
2018-07-01 17:10:51,440 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}

執(zhí)行update底燎、insert、delete的時(shí)候弹砚,會(huì)清空緩存
測(cè)試:

@Test
public void testQueryUserById() {
    System.out.println(this.userMapper.queryUserById("1"));
    //sqlSession.clearCache();

    User user=new User();
    user.setName("美女");
    user.setId("1");
    userMapper.updateUser(user);

    System.out.println(this.userMapper.queryUserById("1"));
}

日志:

2018-07-01 17:18:15,128 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2018-07-01 17:18:15,399 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 242355057.
2018-07-01 17:18:15,401 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-07-01 17:18:15,466 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
2018-07-01 17:18:15,492 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
User{id='1', userName='bigGod222', password='123456', name='鵬程', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 13:35:40.0'}
2018-07-01 17:18:15,527 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==>  Preparing: UPDATE tb_user set name = ?, updated = now() WHERE (id = ?); 
2018-07-01 17:18:15,529 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] ==> Parameters: 美女(String), 1(String)
2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.updateUser]-[DEBUG] <==    Updates: 1
2018-07-01 17:18:15,532 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-07-01 17:18:15,533 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
2018-07-01 17:18:15,538 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}

11.2.二級(jí)緩存

mybatis 的二級(jí)緩存的作用域是一個(gè)mapper的namespace 双仍,同一個(gè)namespace中查詢sql可以從緩存中命中。

開啟二級(jí)緩存:

<mapper namespace="com.zpc.mybatis.dao.UserMapper">
    <cache/>
</mapper>

測(cè)試:

@Test
public void testCache() {
    System.out.println(this.userMapper.queryUserById("1"));

    sqlSession.close();
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    System.out.println(mapper.queryUserById("1"));
}

開啟二級(jí)緩存桌吃,必須序列化:

public class User implements Serializable{
    private static final long serialVersionUID = -3330851033429007657L;

日志:

2018-07-01 17:23:39,335 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2018-07-01 17:23:39,664 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 2092769598.
2018-07-01 17:23:39,665 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2018-07-01 17:23:39,712 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] ==> Parameters: 1(String)
2018-07-01 17:23:39,734 [main] [com.zpc.mybatis.dao.UserMapper.queryUserById]-[DEBUG] <==      Total: 1
User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}
2018-07-01 17:23:39,743 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cbd213e]
2018-07-01 17:23:39,744 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 2092769598 to pool.
2018-07-01 17:23:39,746 [main] [com.zpc.mybatis.dao.UserMapper]-[DEBUG] Cache Hit Ratio [com.zpc.mybatis.dao.UserMapper]: 0.5
User{id='1', userName='bigGod222', password='123456', name='美女', age=20, sex=1, birthday='2018-07-01', created='2018-07-01 13:35:40.0', updated='2018-07-01 17:18:15.0'}

關(guān)閉二級(jí)緩存:
不開啟朱沃,或者在全局的mybatis-config.xml 中去關(guān)閉二級(jí)緩存

[圖片上傳失敗...(image-4a9d4f-1588246105621)]

<settings>
    <!--開啟駝峰匹配-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!--開啟二級(jí)緩存,全局總開關(guān),這里關(guān)閉,mapper中開啟了也沒用-->
    <setting name="cacheEnabled" value="false"/>
</settings>

[圖片上傳失敗...(image-6b0c3-1588246105621)]

12.高級(jí)查詢

12.1.表關(guān)系說(shuō)明

[圖片上傳失敗...(image-eac7bb-1588246105621)]

創(chuàng)建order表:
CREATE TABLE tb_order (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) DEFAULT NULL,
order_number varchar(255) DEFAULT NULL,
create datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    private Date created;
    private Date updated;
}

需求說(shuō)明:
[圖片上傳失敗...(image-68f9bf-1588246105621)]

12.2.一對(duì)一查詢

方法一:核心思想擴(kuò)展Order對(duì)象逗物,來(lái)完成映射
新建OrderUser實(shí)體類繼承Order:

public class OrderUser extends Order {
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private Integer sex;
    private Date birthday;
    private Date created;
    private Date updated;
}

OrderMapper接口:

public interface OrderMapper {
     OrderUser queryOrderUserByOrderNumber(@Param("number") String number);
}

配置OrderMapper:

 <mapper namespace="com.zpc.mybatis.dao.OrderMapper">
    <select id="queryOrderUserByOrderNumber" resultType="com.zpc.mybatis.pojo.OrderUser">
      select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
   </select>
</mapper>

測(cè)試:

@Test
public void queryOrderUserByOrderNumber() throws Exception {
    OrderUser orderUser = orderMapper.queryOrderUserByOrderNumber("201807010001");
    System.out.println(orderUser);
}

方法二:面向?qū)ο蟮乃枷氚嶙洌贠rder對(duì)象中添加User對(duì)象。

在Order對(duì)象中添加User屬性:

public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    private Date created;
    private Date updated;
    private User user;
}

接口:

/**
 * 根據(jù)訂單號(hào)查詢訂單用戶的信息
 * @param number
 * @return
 */
Order queryOrderWithUserByOrderNumber(@Param("number") String number);

使用resultType不能完成自動(dòng)映射翎卓,需要手動(dòng)完成結(jié)果集映射resultMap:

 <resultMap id="OrderUserResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
     <id column="id" property="id"/>
     <!--association:完成子對(duì)象的映射-->
     <!--property:子對(duì)象在父對(duì)象中的屬性名-->
     <!--javaType:子對(duì)象的java類型-->
     <!--autoMapping:完成子對(duì)象的自動(dòng)映射契邀,若開啟駝峰,則按駝峰匹配-->
     <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
         <id column="user_id" property="id"/>
     </association>
 </resultMap>

 <select id="queryOrderWithUserByOrderNumber" resultMap="OrderUserResultMap">
   select * from tb_order o left join tb_user u on o.user_id=u.id where o.order_number = #{number}
</select>

測(cè)試:

@Test
public void queryOrderWithUserByOrderNumber() throws Exception {
    Order order = orderMapper.queryOrderWithUserByOrderNumber("201807010001");
    System.out.println(order.getUser());
}

12.3.一對(duì)多查詢

一對(duì)多查詢:查詢訂單失暴,查詢出下單人信息并且查詢出訂單詳情坯门。

Order類:

public class Order {
    private Integer id;
    private Long userId;
    private String orderNumber;
    private Date created;
    private Date updated;
    private User user;
    private List<OrderDetail> detailList;
}
public class OrderDetail {
    private Integer id;
    private Integer orderId;
    private Double totalPrice;
    private Integer status;
}

接口:

/**
 * 根據(jù)訂單號(hào)查詢訂單用戶的信息及訂單詳情
 * @param number
 * @return
 */
Order queryOrderWithUserAndDetailByOrderNumber(@Param("number") String number);

Mapper映射:

<resultMap id="OrderUserDetailResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
    <id column="id" property="id"/>
    <!--collection:定義子對(duì)象集合映射-->
    <!--association:完成子對(duì)象的映射-->
    <!--property:子對(duì)象在父對(duì)象中的屬性名-->
    <!--javaType:子對(duì)象的java類型-->
    <!--autoMapping:完成子對(duì)象的自動(dòng)映射,若開啟駝峰逗扒,則按駝峰匹配-->
    <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
        <id column="user_id" property="id"/>
    </association>
    <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
        <id column="id" property="id"/>
    </collection>
</resultMap>

 <select id="queryOrderWithUserAndDetailByOrderNumber" resultMap="OrderUserDetailResultMap">
   select * from tb_order o
   left join tb_user u on o.user_id=u.id
   left join tb_orderdetail od on o.id=od.order_id
   where o.order_number = #{number}
</select>

測(cè)試:

@Test
public void queryOrderWithUserAndDetailByOrderNumber() throws Exception {
    Order order = orderMapper.queryOrderWithUserAndDetailByOrderNumber("201807010001");
    System.out.println(order.getUser());
    System.out.println(order.getDetailList());
}

12.4.多對(duì)多查詢

多對(duì)多查詢:查詢訂單古戴,查詢出下單人信息并且查詢出訂單詳情中的商品數(shù)據(jù)。

OrderDetail類

public class OrderDetail {
    private Integer id;
    private Integer orderId;
    private Double totalPrice;
    private Integer status;
    private Item item;
}

public class Item {
    private Integer id;
    private String itemName;
    private Float itemPrice;
    private String itemDetail;
}

接口:

/**
 * 根據(jù)訂單號(hào)查詢訂單用戶的信息及訂單詳情及訂單詳情對(duì)應(yīng)的商品信息
 * @param number
 * @return
 */
Order queryOrderWithUserAndDetailItemByOrderNumber(@Param("number") String number);

Mapper配置:

<resultMap id="OrderUserDetailItemResultMap" type="com.zpc.mybatis.pojo.Order" autoMapping="true">
    <id column="id" property="id"/>
    <association property="user" javaType="com.zpc.mybatis.pojo.User" autoMapping="true">
        <id column="user_id" property="id"/>
    </association>
    <collection property="detailList" javaType="List" ofType="com.zpc.mybatis.pojo.OrderDetail" autoMapping="true">
        <id column="detail_id" property="id"/>
        <association property="item" javaType="com.zpc.mybatis.pojo.Item" autoMapping="true">
            <id column="item_id" property="id"/>
        </association>
    </collection>
</resultMap>

 <select id="queryOrderWithUserAndDetailItemByOrderNumber" resultMap="OrderUserDetailItemResultMap">
   select * ,od.id as detail_id from tb_order o
   left join tb_user u on o.user_id=u.id
   left join tb_orderdetail od on o.id=od.order_id
   left join tb_item i on od.item_id=i.id
   where o.order_number = #{number}
</select>

測(cè)試:

@Test
public void queryOrderWithUserAndDetailItemByOrderNumber() throws Exception {
    Order order = orderMapper.queryOrderWithUserAndDetailItemByOrderNumber("201807010001");
    System.out.println(order);
    System.out.println(order.getUser());
    System.out.println(order.getDetailList());
}

至此缴阎,目錄結(jié)構(gòu)如下:

[圖片上傳失敗...(image-ade682-1588246105621)]

數(shù)據(jù)庫(kù)腳本:
CREATE TABLE tb_order (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) DEFAULT NULL,
order_number varchar(255) DEFAULT NULL,
create datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO tb_order VALUES (‘1’, ‘2’, ‘201807010001’, ‘2018-07-01 19:38:35’, ‘2018-07-01 19:38:40’);

CREATE TABLE tb_item (
id int(11) NOT NULL,
itemName varchar(255) DEFAULT NULL,
itemPrice decimal(10,2) DEFAULT NULL,
itemDetail varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO tb_item VALUES (‘1’, ‘襪子’, ‘29.90’, ‘香香的襪子’);
INSERT INTO tb_item VALUES (‘2’, ‘套子’, ‘99.99’, ‘岡本001’);

CREATE TABLE tb_orderdetail (
id int(11) NOT NULL AUTO_INCREMENT,
order_id int(11) DEFAULT NULL,
total_price decimal(10,0) DEFAULT NULL,
item_id int(11) DEFAULT NULL,
status int(10) unsigned zerofill DEFAULT NULL COMMENT ‘0成功非0失敗’,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO tb_orderdetail VALUES (‘1’, ‘1’, ‘10000’, ‘1’, ‘0000000001’);
INSERT INTO tb_orderdetail VALUES (‘2’, ‘1’, ‘2000’, ‘2’, ‘0000000000’);

12.5.resultMap的繼承

[圖片上傳失敗...(image-697c5-1588246105621)]

12.6.高級(jí)查詢的整理

resutlType無(wú)法幫助我們自動(dòng)的去完成映射允瞧,所以只有使用resultMap手動(dòng)的進(jìn)行映射。
type 結(jié)果集對(duì)應(yīng)的數(shù)據(jù)類型 id 唯一標(biāo)識(shí)蛮拔,被引用的時(shí)候述暂,進(jìn)行指定。

<resultMap type="Order" id="orderUserLazyResultMap">
<!—定義pojo中的單個(gè)對(duì)象的 property 定義對(duì)象的屬性名建炫, javaType 屬性的類型畦韭,
        <association property="user" javaType="User" autoMapping="true">
            <id />
        </association>
<!—如果屬性是集合使用collection ,javaType 集合的類型,ofType 表示集中的存儲(chǔ)的元素類型
        <collection property="details" javaType="List" ofType="OrderDetail" autoMapping="true">
            <id />
</resultMap>

13.延遲加載

后續(xù)補(bǔ)充

14.如果sql語(yǔ)句中出現(xiàn)’<’的解決方案

14,1肛跌,使用xml中的字符實(shí)體

[圖片上傳失敗...(image-47ceaf-1588246105621)]

因?yàn)闃I(yè)務(wù)艺配,需要在mybatis中,使用到大于號(hào)衍慎,小于號(hào)转唉,所以就在SQL中直接使用了。

  • SELECT * FROM test WHERE 1 = 1 AND start_date <= CURRENT_DATE AND end_date >= CURRENT_DATE
    可是稳捆,在執(zhí)行時(shí)赠法,總報(bào)錯(cuò)誤:
    ```Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 74; columnNumber: 17; ``元素內(nèi)容必須由格式正確的字符數(shù)據(jù)或標(biāo)記組成。
    把AND start_date >= CURRENT_DATE AND end_date <= CURRENT_DATE去掉乔夯,就沒有問題砖织,所以確定是因?yàn)榇笥谔?hào),小于號(hào)引起的問題末荐。

于是就想到了特殊符號(hào)侧纯,于是用了轉(zhuǎn)義字符把>和<替換掉,然后就沒有問題了甲脏。

  • SELECT * FROM test WHERE 1 = 1 AND start_date <= CURRENT_DATE AND end_date >= CURRENT_DATE
    案例:
1.<if test="startDateTime!=null"> and mm.ttime &gt; to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss')</if>  
2.<if test="endDateTime!=null"> and mm.ttime &lt;= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss')</if>  

14,2,使用<![CDATA[ < ]]>

案例1:

<![CDATA[ 
       and mm.ttime > to_date(#{startDateTime},'yyyy-mm-dd hh24:mi:ss') 
      and mm.ttime <= to_date(#{endDateTime},'yyyy-mm-dd hh24:mi:ss') 
]]>  

案例2:

mapper文件示例代碼 :

and (t1.status <![CDATA[ >= ]]> 1  and  t1.status <![CDATA[ <= ]]> 2)
上述代碼其實(shí)對(duì)應(yīng)的sql:
and (t1.status > =1 andt1.status <= 2)

注意:

使用<![CDATA[ ]]>標(biāo)記的sql語(yǔ)句中的<where> <if>等標(biāo)簽不會(huì)被解析眶熬。

CDATA 部分中的所有內(nèi)容都會(huì)被解析器忽略妹笆。
CDATA 部分由 "<![CDATA[" 開始,由 "]]>" 結(jié)束

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末聋涨,一起剝皮案震驚了整個(gè)濱河市晾浴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牍白,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抖棘,死亡現(xiàn)場(chǎng)離奇詭異茂腥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)切省,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門最岗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人朝捆,你說(shuō)我怎么就攤上這事般渡。” “怎么了芙盘?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵驯用,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我儒老,道長(zhǎng)蝴乔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任驮樊,我火速辦了婚禮薇正,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘囚衔。我一直安慰自己挖腰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布练湿。 她就那樣靜靜地躺著猴仑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞠鲜。 梳的紋絲不亂的頭發(fā)上宁脊,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音贤姆,去河邊找鬼榆苞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霞捡,可吹牛的內(nèi)容都是我干的坐漏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赊琳!你這毒婦竟也來(lái)了街夭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤躏筏,失蹤者是張志新(化名)和其女友劉穎板丽,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體趁尼,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡埃碱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酥泞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砚殿。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖芝囤,靈堂內(nèi)的尸體忽然破棺而出似炎,到底是詐尸還是另有隱情,我是刑警寧澤悯姊,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布羡藐,位于F島的核電站,受9級(jí)特大地震影響挠轴,放射性物質(zhì)發(fā)生泄漏传睹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一岸晦、第九天 我趴在偏房一處隱蔽的房頂上張望欧啤。 院中可真熱鬧,春花似錦启上、人聲如沸邢隧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)倒慧。三九已至,卻和暖如春包券,著一層夾襖步出監(jiān)牢的瞬間纫谅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工溅固, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留付秕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓侍郭,卻偏偏與公主長(zhǎng)得像询吴,于是被迫代替她去往敵國(guó)和親掠河。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353