天天看點

Mybatis架構入門Mybatis入門程式Mybatis的mapper代理 映射檔案全局配置檔案動态SQL分頁助手PageHelperMybatis緩存機制

mybatis采用 ORM 思想解決了實體和資料庫映射的問題,對 jdbc 進行了封裝,屏蔽了 jdbc api 底層通路細節,使我們不用與 jdbc api 打交道,就可以完成對資料庫的持久化操作。

ORM:對象關系映射(Object Relational Mapping),以面向對象的思想來操作資料庫
  1. 對象就是javabean對象
  2. 關系就是資料表
  3. javabean屬性與表字段一一對應

mybatis的兩種開發方式

  1. 使用原生接口
  2. Mapper代理實作自定義接口

Mybatis入門程式

1. pom.xml

<dependencies>

       <dependency>

           <groupId>org.mybatis</groupId>

           <artifactId>mybatis</artifactId>

           <version>3.4.5</version>

       </dependency>

           <groupId>mysql</groupId>

           <artifactId>mysql-connector-java</artifactId>

           <version>8.0.21</version>

           <groupId>log4j</groupId>

           <artifactId>log4j</artifactId>

           <version>1.2.17</version>

           <groupId>junit</groupId>

           <artifactId>junit</artifactId>

           <version>4.13</version>

           <scope>test</scope>

       <!--lombok簡化實體類編寫-->

           <groupId>org.projectlombok</groupId>

           <artifactId>lombok</artifactId>

           <version>1.18.20</version>

   </dependencies>

   <build>

       <resources>

           <!-- 表示編譯java源碼時,包含src/main/java和src/main/resources目錄下的xml、properties一起 -->

           <!--如果mapper.xml在src/main/java目錄下,就必須做這個配置,不然編譯後會丢棄mapper.xml檔案-->

           <resource>

               <directory>src/main/java</directory>

               <includes>

                   <include>**/*.xml</include>

                   <include>**/*.properties</include>

               </includes>

           </resource>

               <directory>src/main/resources</directory>

       </resources>

   </build>

2. 建立Account表

create table t_account(

 id int primary key auto_increment,

 username varchar(11),

 password varchar(11),

 age int

);

3. 建立實體類Account

@Data

@AllArgsConstructor

@NoArgsConstructor

public class Account {

   private long id;

   private String username;

   private String password;

   private int age;

}

4. 建立IAccountDao接口

接口中每一個方法都代表一個SQL語句,SQL語句寫在mapper檔案中

public interface IAccountDao {

   //查詢一個使用者

   Account selectAccountById(Integer id);

5. 建立SQL映射檔案

建議不同表的操作放在不同的mapper檔案中

在接口同一目錄下,建立與接口同名的檔案

IAccountDao.xml

,來編寫SQL語句

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace命名空間:推薦使用dao接口的全限定名稱-->

<mapper namespace="dao.IAccountDao">

   <!--id是要執行SQL語句的唯一辨別,推薦使用dao接口中的方法名稱

       resultType:告訴mybatis,将查詢到的資料指派給哪個類的對象,使用實體類的全限定名稱

       #{accountId}:占位符,表示從java程式中傳來的資料

   -->

   <select id="selectAccountById" resultType="domain.Account">

       select * from t_account where id=#{accountId}

   </select>

</mapper>

6. 建立主配置檔案

這裡連接配接資料庫的url的參數的大小寫敏感

&amp;characterEncoding=utf-8

mybatis.xml包含了對 MyBatis 系統的核心設定,包括擷取資料庫連接配接執行個體的資料源(DataSource)以及決定事務作用域和控制方式的事務管理器(TransactionManager)

<!DOCTYPE configuration

       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

       "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

   <!--設定日志-->

   <settings>

       <setting name="logImpl" value="STDOUT_LOGGING"/>

   </settings>

   <!--配置mybatis的運作環境。可以配置多個環境,選擇其中一個環境-->

   <environments default="development">

       <environment id="development">

           <!--事務管理-->

           <transactionManager type="JDBC"/>

           <!--配置資料源:建立Connection對象-->

           <dataSource type="POOLED">

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

               <property name="url" value="jdbc:mysql://localhost:3306/eesy?useUnicode=true&amp;characterEncoding=utf-8"/>

               <property name="username" value="ggbond"/>

               <property name="password" value="xxxx"/>

           </dataSource>

       </environment>

   </environments>

   <!--指定mapper檔案的位置,進而找到SQL語句-->

   <mappers>

       <!--resource屬性從類路徑target/classes開始-->

       <mapper resource="dao/IAccountDao.xml"></mapper>

   </mappers>

</configuration>

7. 測試執行

public class MyTest {

   @Test

   public void testSelectAccountById() throws IOException {

       //1.定義mybatis主配置檔案的位置,從類路徑開始的相對路徑

       String config="mybatis.xml";

       //2.使用mybatis架構的工具類Resources來讀取主配置檔案為流對象

       InputStream is = Resources.getResourceAsStream(config);

       //3.使用SqlSessionFactoryBuilder建立SqlSessionFactory對象

       SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

       //4.擷取sqlSession對象

       SqlSession sqlSession = factory.openSession();

       //5.指定要執行的SQL語句 = namespace + "." + id

       String sqlId="dao.IAccountDao"+"."+"selectAccountById";

       //6.通過sqlSession的方法,執行SQL語句

       Account account=sqlSession.selectOne(sqlId,2);

       System.out.println(account);

       //7.關閉sqlSession對象

       sqlSession.close();

   }

注意

1. 占位符 #{}

如果傳給mybatis的是一個對象,那麼使用

#{屬性名}

占位符指派,mybatis通過get方法來擷取值

2. 事務

mybatis執行SQL語句預設是手動送出事務模式:在做insert、update、delete後需要手動送出事務

       sqlSession.commit();

mybatis相關對象

1. Resources

作用:讀取類路徑中的主配置檔案為流對象

        //1.定義mybatis主配置檔案的位置,從類路徑開始的相對路徑

        String config="mybatis.xml";

        //2.使用mybatis架構的工具類Resources來讀取主配置檔案為流對象

        InputStream is = Resources.getResourceAsStream(config);

2. SqlSessionFactoryBuilder

作用:建立SqlSessionFactory對象

        //3.使用SqlSessionFactoryBuilder建立SqlSessionFactory對象

        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

3. SqlSessionFactory

SqlSessionFactory是重量級對象:建立此對象需要使用更多的資源和時間。在項目中有一個即可(在工具類中放在靜态代碼塊内)

作用:是SqlSession的工廠,就是建立SqlSession對象。

方法:

  1. openSession()

    :擷取一個預設的SqlSession對象, 預設是需要手工送出事務的。
  2. openSession(boolean)

    : boolean參數表示是否自動送出事務。

true: 建立一個自動送出事務的SqlSession

false: 等同于沒有參數的openSession

4. SqlSession

SqlSession中提供所有執行SQL的方法

selectOne:執行sql語句,最多得到一行記錄,多餘1行是錯誤。

selectList:執行sql語句,傳回多行資料

selectMap:執行sql語句的,得到一個Map結果

insert:執行insert語句

update:執行update語句

delete:執行delete語句

commit:送出事務

rollback:回顧事務

注意SqlSession對象不是線程安全的(每次使用都要先去擷取新的對象), 使用的步驟:

①:在方法的内部,執行sql語句之前,先擷取SqlSession對象

②:調用SqlSession的方法,執行sql語句

③:關閉SqlSession對象,執行SqlSession.close()

        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-config.dtd">

    <!--設定日志-->

    <settings>

        <setting name="logImpl" value="STDOUT_LOGGING"/>

    </settings>

    <!--配置mybatis的運作環境。可以配置多個環境,選擇其中一個環境-->

    <environments default="development">

        <environment id="development">

            <!--事務管理-->

            <transactionManager type="JDBC"/>

            <!--配置資料源:建立Connection對象-->

            <dataSource type="POOLED">

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

                <property name="url" value="jdbc:mysql://localhost:3306/eesy?useUnicode=true&amp;characterEncoding=utf-8"/>

                <property name="username" value="ggbond"/>

                <property name="password" value="xxxx"/>

            </dataSource>

        </environment>

    </environments>

    <!--指定mapper檔案的位置,進而找到SQL語句-->

    <mappers>

        <!--resource屬性從類路徑target/classes開始-->

        <mapper resource="dao/IAccountDao.xml"></mapper>

    </mappers>

使用模闆和工具類簡化開發

模闆

mybatis-mapper

        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="dao接口的全限定名稱">

    <!--使用insert、update、delete、select标簽寫SQL -->

mybatis-config

工具類

/**

 * 工具類,建立SqlSession對象

 */

public class MyBatisUtil {

    private static SqlSessionFactory factory =null;

    static{

        //1.定義mybatis主配置檔案的位置,檔案的類路徑

        try {

            //2.使用mybatis架構的工具類Resources來讀取主配置檔案為流對象

            InputStream is = Resources.getResourceAsStream(config);

            //3.使用SqlSessionFactoryBuilder建立SqlSessionFactory對象

            factory = new SqlSessionFactoryBuilder().build(is);

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**

     * 擷取SqlSession對象的方法

     * @return

     */

    public static SqlSession getSqlSession(){

        SqlSession sqlSession=null;

        if (factory!=null){

            sqlSession=factory.openSession();

        return sqlSession;

使用:

    @Test

    public void testUtil() throws IOException {

        //1.擷取SqlSession對象

        SqlSession sqlSession = MyBatisUtil.getSqlSession();

        //2.指定要執行的SQL語句

        String sqlId="dao.IAccountDao"+"."+"insertAccount";

        //3.通過sqlSession的方法,執行SQL語句

        Account account = new Account(7,"琪琪","qiqi",20);

        int i = sqlSession.insert(sqlId,account);

        System.out.println(i);

        //4.送出事務

        sqlSession.commit();

        //5.關閉sqlSession對象

        sqlSession.close();

Mybatis的mapper代理

使用傳統開發方式

需要建立接口實作類,實作接口方法

public class AccountDaoImpl implements IAccountDao {

    @Override

    public Account selectAccountById(Integer id) {

        String sqlId="dao.IAccountDao"+"."+"selectAccountById";

        Account account = sqlSession.selectOne(sqlId, id);

        //4.關閉sqlSession對象

        return account;

    public int insertAccount(Account account) {

        return i;

    public List<Account> selectAccounts() {

        String sqlId="dao.IAccountDao"+"."+"selectAccounts";

        List<Account> accounts = sqlSession.selectList(sqlId);

        return accounts;

傳統開發方式的分析

在前面例子中自定義 Dao 接口實作類時發現一個問題:Dao 的實作類其實并沒有幹什麼實質性的工作,它僅僅就是通過 SqlSession 的相關 API 定位到映射檔案 mapper 中相應 id 的 SQL 語句,真正對 DB 進行操作的工作其實是由架構通過 mapper 中的 SQL 完成的。是以,MyBatis 架構就抛開了 Dao 的實作類,直接定位到映射檔案mapper 中的相應 SQL 語句,對 DB 進行操作。這種對 Dao 的實作方式稱為Mapper 的動态代理方式。

Mapper 代理實作資料庫操作(重點)

Mapper 動态代理方式無需程式員實作 Dao 接口。接口是由 MyBatis 結合映射檔案自動生成的動态代理實作的。

  1. 需要dao接口和對應的mapper檔案,不需要接口的實作類mapper檔案的要求:
    1. mapper檔案中的namespace是dao接口的全限定名稱
    2. mapper檔案中 标簽的id是dao接口方法名稱
  1. 以上操作綁定了mapper檔案是接口的實作類
  2. 隻需調用 SqlSession 的

    getMapper()

    方法,即可擷取指定接口的實作類對象。該方法的參數為指定 Dao 接口類的 class 值。

        //2.擷取接口的代理對象(将接口和配置檔案綁定)

        IAccountDao dao = sqlSession.getMapper(IAccountDao.class);

        Account account = dao.selectAccountById(1);

        System.out.println(account);

映射檔案

mapper.xml

1. SQL語句中參數的傳遞

通過java代碼将參數傳入到mapper檔案中的sql語句。 參數主要是指dao接口方法的形參

parameterType(可選)

  1. parameterType是标簽屬性,表示接口中方法參數的類型, 屬性值是類型的全限定名或别名。
  2. 這個屬性是可選的,因為 MyBatis 可以推斷出具體傳入語句的參數,預設值為未設定(unset)。
  3. 接口中方法的參數從 java 代碼傳入到 mapper 檔案的 sql 語句。

第一個用法: java類型的全限定類型名稱   parameterType="java.lang.Integer"

第二個用法: mybatis定義的java類型的别名  parameterType="int"

parameterType:mybatis通過反射機制可以擷取 dao接口方法參數的類型, 可以不寫

<select id="selectById"  parameterType="integer"

                 resultType="com.bjpowernode.domain.Student">

   select id,name,email,age from student where id=#{studentId}

</select>

dao接口方法有一個參數

//dao接口的方法形參是一個簡單類型的

//簡單類型: java基本資料類型和String

Student selectByEmail(String email);

<!--

   dao接口的方法形參是一個簡單類型的

   mapper檔案,擷取這個參數值,使用#{任意字元}

-->

<select id="selectByEmail" resultType="com.bjpowernode.domain.Student">

    select id,name,email,age from student where email=#{studentEmail}

dao接口方法有多個參數

@Param

: 命名參數,在方法的形參前面使用的,定義參數名。這個名稱可以用在mapper檔案中。

在dao接口,方法的定義:

/*

  多個簡單類型的參數

  使用@Param命名參數, 注解是mybatis提供的

  位置:在形參定義的前面

  屬性:value 自定義的參數名稱

List<Student> selectByNameOrAge(@Param("myname") String name,

                                @Param("myage") Integer age);

mapper檔案:

   多個簡單類型的參數.

   當使用了@Param命名後,例如@Param("myname").

   在mapper中,使用#{命名的參數}, 例如 #{myname}

<select id="selectByNameOrAge" resultType="com.bjpowernode.domain.Student">

    select id,name,email,age from student where name=#{myname} or age=#{myage}

dao接口方法參數是一個對象

方法的形參是一個java對象。這個java對象表示多個參數。使用對象的屬性作為參數使用

java對象

public class Student {

    private Integer id;

    private String name;

    private String email;

    private Integer age;

    //set|get方法

public class QueryParam {

    private Object p1;

    private Object p2;

dao接口中的方法定義

 * 一個java對象作為參數( 對象由屬性, 每個屬性有set,get方法)

List<Student> selectByObject(Student student);

List<Student> selectByQueryParam(QueryParam param);

mapper檔案

   一個java對象作為方法的參數,使用對象的屬性作為參數值使用

   簡單的文法: #{屬性名} , mybatis調用此屬性的getXXX()方法擷取屬性值

<select id="selectByObject" resultType="com.bjpowernode.domain.Student">

    select id,name,email,age from student where name=#{name} or age=#{age}

<select id="selectByQueryParam" resultType="com.bjpowernode.domain.Student">

     select id,name,email,age from student where name=#{p1} or age=#{p2}

<!--負責的文法格式: #{屬性名,javaType=java類型的全限定名稱,jdbcType=mybatis中定義列的資料類型}

 javaType, jdbcType 的類型 MyBatis 可以檢測出來,一般不需要設定。常用格式 #{ property }-->

        select id,name,email,age from student where

        name=#{name,javaType=java.lang.String,jdbcType=VARCHAR}

        or

        age=#{age,javaType=java.lang.Integer,jdbcType=INTEGER}

2. #和$的差別

# 占位符

文法: #{字元}

mybatis處理#{} 使用jdbc對象是 PrepareStatment對象

             resultType="com.bjpowernode.domain.Student">

    select id,name,email,age from student where id=#{studentId}

mybatis會建立PrepareStatement對象,執行sql語句

String sql=" select id,name,email,age from student where id=?";

PrepareStatement pst = conn.prepareStatement(sql);

pst.setInt(1,1001);  //傳遞參數

ResultSet rs  = pst.executeQuery(); //執行sql語句

#{}特點:

1)使用的PrepareStatement對象,執行sql語句,效率高。

2)使用的PrepareStatement對象,能避免sql注入, sql語句執行更安全。

3) #{} 常常作為 列值使用的, 位于等号的右側, #{}位置的值和資料類型有關的。

$ 占位符

文法 : ${字元}

mybatis執行${}占位符的sql語句,使用Statement對象

    select id,name,email,age from student where id=${studentId}

</select> 

${} 表示字元串連接配接, 把sql語句的其他内容和 ${}内容使用 字元串(+) 連接配接的方式連在一起

String sql="select id,name,email,age from student where id=" + "1001";

mybatis建立Statement對象, 執行sql語句。

Statement stmt  = conn.createStatement(sql);

ResultSet rs  = stmt.executeQuery();

${} 的特點

1)使用Statement對象,執行sql語句,效率低

2)${}占位符的值,使用的字元串連接配接方式, 有sql注入的風險。 有代碼安全的問題

  1. ${} 資料是原樣使用的(傳什麼就用什麼), 不會區分資料類型。

4)${} 常用作 表名或者列名, 在能保證資料安全的情況下使用 ${}

3. 輸出結果的封裝

輸出結果的封裝:mybatis執行SQL語句,将結果集轉為java對象

1. resultType

  1. 在執行select時使用, 作為<select>标簽的屬性出現的。
  2. 表示查詢結果的類型,mysql執行sql語句,得到java對象的類型。值有兩種寫法:
    1. java類的全限定名稱
    2. 使用類的别名

對象類型

resultType屬性現在使用java類型的全限定名稱,表示mybatis執行sql,把ResultSet中的資料轉為Student類型的對象

# dao接口方法

Student selectById(Integer id);

# mapper檔案

<select id="selectById" resultType="com.bjpowernode.domain.Student">

mybatis會執行以下操作:

  1. 調用com.bjpowernode.domain.Student的無參數構造方法,建立對象

Student student = new Student(); //使用反射建立對象

  1. 同名的列指派給同名的屬性

student.setId( rs.getInt("id"));

student.setName(rs.getString("name"));

  1. 得到java對象, 如果dao接口傳回值是List集合, mybatis把student對象放入到List集合

簡單類型

基本類型和String

long countStudent();

# mapper檔案,執行sql語句,得到是一個值(一行一列)

<select id="countStudent" resultType="java.lang.Long">

    select count(*) from student

Map

mybatis執行sql,把ResultSet轉為map:列名為key,列值為value

注意:如果sql執行得到一行,是可以轉為map的;但多于一行會報錯,無法轉換為map

//查詢結果傳回是一個Map

Map<Object,Object> selectMap(@Param("stuid") Integer id);

<select id="selectMap" resultType="java.util.HashMap">

    select id,name,email from student where id != #{stuid}

2. resultMap(推薦)

resultMap:結果映射。可以自定義 列名 和 java對象屬性 的對應關系。常用在列名和屬性名不同的情況

用法:

1.先定義resultMap标簽,指定列名和屬性名稱對應關系

2.在select标簽使用resultMap屬性,指定上面定義的resultMap的id值

<!--使用resultMap定義列和屬性的關系-->

<!--定義resultMap

    id:給resultMap的映射關系起個名稱,唯一值

    type:java類型的全限定名稱

<resultMap id="customMap" type="com.bjpowernode.vo.CustomObject">

    <!--定義列名和屬性名的對應-->

    <!--主鍵類型使用id标簽-->

    <id column="id" property="cid" />

    <!--非主鍵類型使用result标簽-->

    <result column="name" property="cname" />

    <!--列名和屬性名相同不用定義-->

    <result column="email" property="email" />

    <result column="age" property="age" />

</resultMap>

<!--使用resultMap屬性,指定映射關系的id

    resultMap和resultType 不能同時使用, 二選一。

<select id="selectById2" resultMap="customMap">

  select id,name,email,age from student where id=#{stuid}

3. 列名和java對象屬性名稱不一樣的解決方式

  1. 使用resultMap: 自定義列名和屬性名稱對應關系
  2. 使用resultType: 使用列别名(as),讓别名和java對象屬性名稱一樣

4. 模糊查詢 like

類似于一個基本參數吧

dao接口方法

List<Student> selectLikeOne(@Param("name") String name);

mapper

<select id="selectLikeOne" resultType="com.bjpowernode.domain.Student">

    select * from student where name like #{name}

執行like

@Test

public void testLikeOne(){

    SqlSession sqlSession = MyBatisUtil.getSqlSession();

    StudentDao dao  = sqlSession.getMapper(StudentDao.class);

    String name="%李%";

    List<Student> students = dao.selectLikeOne(name);

    sqlSession.close();

    students.forEach( stu-> System.out.println(stu));

5. 自定義類的别名

mybatis提供的對java類的全限定名稱進行自定義别名

自定義别名的步驟:

1)在mybatis主配置檔案,使用 typeAliases标簽聲明别名

<typeAliases>

    <!--第一種文法格式

        type:java類型的全限定名稱(自定義類型)

        alias:自定義别名

    -->

    <typeAlias type="com.bjpowernode.domain.Student" alias="stu" />

</typeAliases>

2)在mapper檔案中, resultType="别名"

resultType="别名"

<select id="selectById"  parameterType="integer" resultType="stu">

全局配置檔案

config.xml

mybatis配置檔案兩大類:

  1. mybatis主配置檔案,提供mybatis全局設定的。包含的内容 日志, 資料源,mapper檔案位置
  2. mapper檔案: 寫sql語句的。 一個表一個mapper檔案

1. settings 設定标簽

settings是mybatis的全局設定,影響整個mybatis的運作。 這個設定一般使用預設值就可以了。

<settings>

  <setting name="cacheEnabled" value="true"/>

  <setting name="lazyLoadingEnabled" value="true"/>

  <setting name="multipleResultSetsEnabled" value="true"/>

  <setting name="useColumnLabel" value="true"/>

  <setting name="useGeneratedKeys" value="false"/>

  <setting name="autoMappingBehavior" value="PARTIAL"/>

  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>

  <setting name="defaultExecutorType" value="SIMPLE"/>

  <setting name="defaultStatementTimeout" value="25"/>

  <setting name="defaultFetchSize" value="100"/>

  <setting name="safeRowBoundsEnabled" value="false"/>

  <setting name="mapUnderscoreToCamelCase" value="false"/>

  <setting name="localCacheScope" value="SESSION"/>

  <setting name="jdbcTypeForNull" value="OTHER"/>

  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>

</settings>

2. typeAliases 别名标簽

設定别名

 <typeAliases>

        <!--第一種文法格式

            type:java類型的全限定名稱(自定義類型)

            alias:自定義别名

            優點: 别名可以自定義

            缺點: 每個類型必須單獨定義

        -->

        <typeAlias type="com.bjpowernode.domain.Student" alias="stu" />

        <typeAlias type="com.bjpowernode.vo.QueryParam" alias="qp" />

        <!--第二種方式

            name:包名, mybatis會把這個包中所有類名作為别名(不用區分大小寫)

            優點:使用友善,一次給多個類定義别名

            缺點: 别名不能自定義,必須是類名。

        <package name="com.bjpowernode.domain" />

        <package name="com.bjpowernode.vo" />

    </typeAliases>

3. environments 環境标簽

environments: 環境标簽, 在他裡面可以配置多個environment

       屬性: default ,必須是某個environment的id屬性值。 表示mybatis預設連接配接的資料庫

environment: 表示一個資料庫的連接配接資訊。

       屬性: id 自定義的環境的辨別。 唯一值。

transactionManager:事務管理器

       屬性:  type 表示事務管理器的類型。

       屬性值:1)JDBC: 使用Connection對象, 由mybatis自己完成事務的處理。

             2) MANAGED: 管理,表示把事務的處理交給容器實作(由其他軟體完成事務的送出,復原)

dataSource: 資料源,建立的Connection對象,連接配接資料庫。

       屬性:  type 資料源的類型

       屬性值:1) POOLED, mybatis會在記憶體中建立PooledDataSource類,管理多個Connection連接配接對象,使                           用的連接配接池

             2) UNPOOLED ,不使用連接配接池, mybatis建立一個UnPooledDataSource這個類, 每次執行sql                           語句先建立Connection對象,再執行sql語句,最後關閉Connection

             3) JNDI : java的命名和目錄服務。

<environments default="online">

            <!--配置資料源: 建立Connection對象。-->

                <!--driver:驅動的内容-->

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

                <!--連接配接資料庫的url-->

                <property name="url"

                          value="jdbc:mysql://localhost:3306/springdb"/>

                <!--使用者名-->

                <property name="username" value="root"/>

                <!--密碼-->

                <property name="password" value="123"/>

        <!-- 項目上線後使用的資料庫 -->

        <environment id="online">

                <property name="username" value="admin"/>

                <property name="password" value="123456"/>

4. 使用資料庫屬性配置檔案(*)

需要把資料庫的配置資訊放到一個單獨檔案中, 獨立管理。 這個檔案擴充名是 properties. 在這個檔案中,使用自定義的key=value的格式表示資料

使用步驟:

1.在resources目錄中,建立xxxx.properties

2.在檔案中,使用 key=value的格式定義資料。

例如

jdbc.url=jdbc:mysq://localhost:3306/springdb

3.在mybatis主配置檔案, 使用

properties

标簽引用外部的屬性配置檔案

4.在使用值的位置, 使用

${key}

擷取key對應的value(等号右側的值)

例子:

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&amp;characterEncoding=utf-8

jdbc.username=root

jdbc.password=123

mybatis主配置檔案

<!--使用外部屬性配置檔案

    resource:指定類路徑下的某個屬性配置檔案

<properties resource="jdbc.properties" />

<environments default="development">

                <property name="driver" value="${jdbc.driver}"/>

                <property name="url" value="${jdbc.url}"/>

                <property name="username" value="${jdbc.username}"/>

                <property name="password" value="${jdbc.password}"/>

         </environment>

</environments>

5. mapper 标簽(*)

使用mapper指定其他mapper檔案的位置, 有兩個常用的方式:

<mappers>

    <!--第一種方式, resources="mapper檔案的路徑"

        優點:檔案清晰。 加載的檔案是明确的。

              檔案的位置比較靈活。

        缺點:檔案比較多, 代碼量會比較大, 管理難度大

    <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>

    <mapper resource="com/bjpowernode/dao/OrderDao.xml"/>

    <!--

       第二種方式,使用<package>

       name:包名, mapper檔案所在的包名。

       特點: 把這個包中的所有mapper檔案,一次加載。

       使用要求:

        1. mapper檔案和dao接口在同一目錄

        2. mapper檔案和dao接口名稱完全一樣。

    <package name="com.bjpowernode.dao" />

    <package name="com.bjpowernode.dao1" />

</mappers>

動态SQL

動态 SQL,通過 MyBatis 提供的各種标簽對條件作出判斷以實作動态拼接SQL 語句。這裡的條件判斷使用的表達式為 OGNL 表達式。常用的動态 SQL标簽有<if>、<where>、<choose/>、<foreach>等。MyBatis 的動态 SQL 語句,與 JSTL 中的語句非常相似。

動态 SQL,主要用于解決查詢條件不确定的情況:在程式運作期間,根據使用者送出的查詢條件進行查詢。送出的查詢條件不同,執行的 SQL 語句不同。若将每種可能的情況均逐一列出,對所有條件進行排列組合,将會出現大量的SQL 語句。此時,可使用動态 SQL 來解決這樣的問題。動态SQL的dao接口方法參數是對象

比較符号轉換為實體符

在 mapper 的動态 SQL 中若出現大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等符号,最好将其轉換為實體符号。否則,XML 可能會出現解析出錯問題。

&:

&amp;

1. if 标簽

文法:

  1. <if test="條件">sql語句</if>

  2. test使用對象的屬性值作為條件

<!--在mapper檔案中-->

<select id="selectStudent" resultType="com.bjpwoernode.domain.Student">

      select *from student

      <if test="條件">

          sql語句

      </if>

示例:

List<Student> selectIf(Student student);

<select id="selectIf" resultType="com.bjpowernode.domain.Student">

    select * from student

    where id=-1

    <if test="name !=null and name!=''">

       or  name = #{name}

    </if>

    <if test="age >0">

        or age &lt; #{age}

2. where 标簽

<if/>标簽的中存在一個比較麻煩的地方:需要在 where 後手工添加 1=1的子句。因為,若 where 後的所有<if/>條件均為 false,而 where 後若又沒有 1=1 子句,則 SQL 中就會隻剩下一個空的 where,SQL 出錯。是以,在where 後,需要添加永為真子句 1=1,以防止這種情況的發生。但當資料量很大時,會嚴重影響查詢效率。

使用<where/>标簽,在有查詢條件為true時,可以自動添加上 where 子句;沒有查詢條件為true時,不會添加 where 子句。需要注意的是,第一個<if/>标簽中的SQL 片斷,可以不包含 and。不過,寫上 and 也不錯,系統會将多出的 and去掉。但其它<if/>中 SQL 片斷的 and,必須要求寫上。否則 SQL 語句将拼接出錯

<where>

    <if test="條件1">sql語句1</if>

    <if test="條件2">sql語句2</if>

</where>

//where

List<Student> selectWhere(Student student);

<!--where-->

<select id="selectWhere" resultType="com.bjpowernode.domain.Student">

    <where>

        <if test="name !=null and name!=''">

            or  name = #{name}

        </if>

        <if test="age >0">

            or age &lt; #{age}

    </where>

3. foreach 循環标簽

使用foreach可以循環數組,list集合, 一般使用在in語句中

标簽屬性:

  1. collection:表示循環的對象是數組,還是list集合。

    如果dao接口方法的形參是數組,collection="array"

    如果dao接口形參是List,collection="list"

  2. open:循環開始時的字元。 sql.append("(");
  3. close:循環結束時字元。 sql.append(")");
  4. item:集合成員, 自定義的變量。 Integer item = idlist.get(i);
  5. separator:集合成員之間的分隔符。 sql.append(",");
  6. #{item 的值}:擷取集合成員的值。

< foreach collection="集合類型" open="開始字元" close="結束字元" item="集合成員" separator="集合成員之間的分隔符">

              #{item 的值}

</ foreach>

循環簡單類型的List

List<Student> selectForeachOne(List<Integer> idlist);

<!--foreach第一種方式, 循環簡單類型的List-->

<select id="selectForeachOne" resultType="com.bjpowernode.domain.Student">

      select * from student

        <if test="list !=null and list.size>0">

            where id in

            <foreach collection="list" open="(" close=")" separator="," item="myid">

                  #{myid}

            </foreach>

public void testSelectForeachOne(){

        //1.擷取SqlSession

        SqlSession session = MyBatisUtil.getSqlSession();

        //2.擷取dao的代理

        StudentDao dao = session.getMapper(StudentDao.class);

        List<Integer> idlist = new ArrayList<>();

        idlist.add(1001);

        idlist.add(1002);

        idlist.add(1003);

        List<Student> students  = dao.selectForeachOne(idlist);

        students.forEach( stu-> System.out.println("stu=="+stu));

        //3.關閉SqlSession對象

        session.close();

循環對象類型的list

//foreach-2

List<Student> selectForeachTwo(List<Student> studentList);

<!--foreach第二種方式, 循環的List<Student>-->

<select id="selectForeachTwo" resultType="com.bjpowernode.domain.Student">

        select * from student

        <if test="list != null and list.size>0">

            <foreach collection="list" open="(" close=")" separator="," item="stu">

                  #{stu.id}

 @Test

 public void testSelectForeachTwo(){

        List<Student> list  = new ArrayList<>();

        Student s1 = new Student();

        s1.setId(1001);

        Student s2 = new Student();

        s2.setId(1002);

        list.add(s1);

        list.add(s2);

        List<Student> students  = dao.selectForeachTwo(list);

4. 代碼片段

<sql/>标簽用于定義 SQL 片斷,以便其它 SQL 标簽複用。而其它标簽使用該 SQL 片斷,需要使用<include/>子标簽。該<sql/>标簽可以定義 SQL 語句中的任何部分,是以<include/>子标簽可以放在動态 SQL 的任何位置。

<!--定義代碼片段-->

<sql id="selectStudent">

</sql>

<sql id="studentFieldList">

    id,name,email

        <include refid="selectStudent" />

        where id=-1

           or  name = #{name}

    </select>

    <select id="selectWhere" resultType="com.bjpowernode.domain.Student">

        select <include refid="studentFieldList"/> from student

        <where>

            <if test="name !=null and name!=''">

                or  name = #{name}

            </if>

            <if test="age >0">

                or age &lt; #{age}

        </where>

分頁助手PageHelper

PageHelper做資料分頁。 在你的select語句後面加入分頁的 sql 内容, 如果你使用的mysql資料庫, 它就是在select * from student 後面加入 limit 語句。

1.加入依賴pagehelper依賴

<dependency>

<groupId>com.github.pagehelper</groupId>

<artifactId>pagehelper</artifactId>

<version>5.1.10</version>

</dependency>

2.在mybatis主配置檔案, 加入plugin聲明

在<environments> 之前加入

<plugins>

   <plugin interceptor ="com.github.pagehelper.PageInterceptor" />

</plugins>    

3.在select語句之前,調用

PageHelper.startPage(頁碼,每頁大小)

。緊跟在這個方法後的第一個 MyBatis 查詢方法會被進行分頁

public void testSelect() throws IOException {

 //擷取第 1 頁,3 條内容(頁碼從1開始)

 PageHelper.startPage(1,3);

  List<Student> studentList = studentDao.selectStudents();

  studentList.forEach( stu -> System.out.println(stu));

對比:

  1. 沒有使用PageHelper

select * from student order by id

  1. 使用PageHelper

SELECT count(0) FROM student 

select * from student order by id LIMIT ? 

Mybatis緩存機制