Mybatis學習總結

Mybatis學習總結().初探Mybatis

回顧JDBC編程php

1.建立Maven工程,導入mysql依賴html

<!-- MySql -->java

<dependency>mysql

    <groupId>mysql</groupId>git

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

    <version>5.1.32</version>spring

</dependency>sql

2.需求:根據用戶id查詢用戶信息數據庫

用戶表:apache

DROP TABLE IF EXISTS `tb_user`;

CREATE TABLE `tb_user` (

`id` bigint(20) NOT NULL AUTO_INCREMENT,

`user_name` varchar(100) DEFAULT NULL COMMENT '用戶名',

`password` varchar(100) DEFAULT NULL COMMENT '密碼',

`name` varchar(100) DEFAULT NULL COMMENT '姓名',

`age` int(10) DEFAULT NULL COMMENT '年齡',

`sex` tinyint(1) DEFAULT NULL COMMENT '性別,1男性,2女性',

`birthday` date DEFAULT NULL COMMENT '出生日期',

`created` datetime DEFAULT NULL COMMENT '建立時間',

`updated` datetime DEFAULT NULL COMMENT '更新時間',

PRIMARY KEY (`id`),

UNIQUE KEY `username` (`user_name`)

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------

-- Records of tb_user

-- ----------------------------

INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '張三', '30', '1', '1984-08-08', '2014-09-19 16:56:04', '2014-09-21 11:24:59');

INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '21', '2', '1991-01-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');

INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '王五', '22', '2', '1989-01-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');

INSERT INTO `tb_user` VALUES ('4', 'zhangwei', '123456', '張偉', '20', '1', '1988-09-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');

INSERT INTO `tb_user` VALUES ('5', 'lina', '123456', '李娜', '28', '1', '1985-01-01', '2014-09-19 16:56:04', '2014-09-19 16:56:04');

INSERT INTO `tb_user` VALUES ('6', 'lilei', '123456', '李磊', '23', '1', '1988-08-08', '2014-09-20 11:41:15', '2014-09-20 11:41:15');

SQL:

SELECT * FROM tb_user WHERE id = ?

3.編寫JDBC程序

/**

* @Description:Jdbc鏈接數據庫

* @author xingyuchao

* @date 2016年8月2日 下午2:42:17

* @version V1.0

*/

public class JDBCTest {

public static void main(String[] args) {

ResultSet resultSet = null;

PreparedStatement preparedStatement = null;

Connection connection = null;

try {

// 加載驅動

Class.forName("com.mysql.jdbc.Driver");

// 建立數據庫鏈接

String url = "jdbc:mysql://127.0.0.1:3306/mybatis";

String user = "root";

String password = "123456";

connection = DriverManager.getConnection(url, user, password);

// 建立statmenet

String sql = "SELECT * FROM tb_user WHERE id = ?";

preparedStatement = connection.prepareStatement(sql);

// 設置參數、執行sql,2個參數,第一個是參數的下標,從1開始,第二個參數數據查詢條件數據

preparedStatement.setLong(1, 1L);

resultSet = preparedStatement.executeQuery();

// 遍歷結果集

while (resultSet.next()) {

System.out.println("ID: " + resultSet.getLong("id"));

System.out.println("userName: " + resultSet.getString("user_name"));

System.out.println("password: " + resultSet.getString("password"));

System.out.println("name: " + resultSet.getString("name"));

}

} catch (Exception e) {

e.printStackTrace();

} finally {

// 釋放鏈接(資源)

if (null != resultSet) {

try {

resultSet.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(null != preparedStatement){

try {

preparedStatement.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if(null != connection){

try {

connection.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

}

}

存在的問題:

一、 加載驅動的問題

每次執行都要加載驅動

驅動名稱硬編碼java代碼中,如需修改驅動名稱時,須要修改java文件再編譯

解決方案:將驅動名稱放置到外部的配置文件中解決。

二、 數據庫鏈接信息硬編碼到java代碼中,解決:外部配置文件解決。

三、 設置參數問題

參數下標硬編碼到java代碼中,須要人工判斷參數位置,使用不便

參數值硬編碼到代碼中,若是要修改參數或者是根據不一樣的參數值查詢,沒法實現,解決:經過參數傳入解決。

但願:可否自動判斷參數下標和類型。

四、 遍歷結果集存在的問題,須要人工判斷字段名以及位置或者參數的類型,致使使用不方便

但願:若是,能將結果集直接映射爲一個pojo對象,那麼使用就方便多了

五、 頻繁的建立鏈接、關閉鏈接,致使資源浪費,影響應用的性能,解決:使用鏈接池解決。

解決:使用Mybatis解決。

Mybatis簡介

Mybatis的前身是iBatis,Apache的一個開源項目,2010年這個項目從Apache遷移到Google Code更名爲Mybatis 以後將版本升級到3.X,其官網:http://blog.mybatis.org/,從3.2版本以後遷移到github,目前最新穩定版本爲:3.2.8。

Mybatis是一個相似於Hibernate的ORM持久化框架,支持普通SQL查詢,存儲過程以及高級映射。Mybatis經過使用簡單的XML或註解用於配置和原始映射,將接口和POJO對象映射成數據庫中的記錄。

因爲Mybatis是直接基於JDBC作了簡單的映射包裝,全部從性能角度來看:JDBC > Mybatis > Hibernate

Mybatis的官網:http://blog.mybatis.org/

下載地址(3.2.8):https://github.com/mybatis/mybatis-3/releases

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

官方文檔(中文版):http://www.mybatis.org/mybatis-3/zh/index.html

mybatis-spring文檔:http://www.mybatis.org/spring/zh/index.html

mybatis手動控制事務:http://toknowme.iteye.com/blog/2226645

Mybatis的總體架構

一、 mybatis配置文件,有2類配置文件

全局配置文件,只能有一個,文件名不是固定的,約定文件名:mybatis-config.xml,配置了運行參數、插件、鏈接池等信息。

Mapper.xml,映射文件,在整個mybatis中能夠有多個配置文件,配置多個Statement(SQL)

二、 經過配置文件構造出SqlSessionFactory

三、 經過SqlSessionFactory獲取到Sqlsession,經過SqlSession就能夠操做數據庫。

四、 SqlSession同底層的執行器來執行Statement(SQL),mybatis提供了2種執行器的實現

基本實現

帶有緩存功能的實現

五、 執行器經過定義的Mapped Statement對象來執行SQL

六、 參數傳入:參數類型有三種,HashMap、基本數據類型、POJO對象

七、 結果輸出:輸出結果集類型有三種,HashMap、基本數據類型、POJO對象

Mybatis使用步驟

1.導入依賴:

<dependency>

    <groupId>org.mybatis</groupId>

    <artifactId>mybatis</artifactId>

    <version>3.2.8</version>

</dependency>

2.編寫全局配置文件 mybatis-config.xml

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true

jdbc.username=root

jdbc.password=123456

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">

<configuration>

    <!-- 加載配置文件 -->

    <properties resource="jdbc.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>

    <!-- <mappers>

        <mapper resource="UserMapper.xml" />

    </mappers> -->

</configuration>

3.構建SqlSessionFactory

public class Mybatis {

public static void main(String[] args) throws Exception {

//定義配置文件名稱

String resource = "mybatis-config.xml";

//經過Resources工具類讀取配置文件

InputStream inputStream = Resources.getResourceAsStream(resource);

//經過SqlSessionFactoryBuilder構造SqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//或獲得SqlSession

SqlSession session = sqlSessionFactory.openSession();

System.out.println(sqlSessionFactory);

System.out.println(session);

}

}

4.配置statement 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 namespace="abc">

    <select id="queryUserById" resultType="cn.zto.mybatis.pojo.User">

        SELECT * FROM tb_user WHERE id = #{id}

    </select>

</mapper>

User.java

public class User {

private Long id;

// 用戶名

private String userName;

// 密碼

private String password;

// 姓名

private String name;

// 年齡

private Integer age;

// 性別,1男性,2女性

private Integer sex;

// 出生日期

private Date birthday;

// 建立時間

private Date created;

// 更新時間

private Date updated;

//getter and setter

}

5.將UserMapper.xml加入到Mybatis全局配置文件中:

<mappers>

    <mapper resource="UserMapper.xml" />

</mappers>

6.根據Id查詢用戶信息

//名稱空間.statemement

User user = session.selectOne("abc.queryUserById", 1);

System.out.println(user);

session.close();

測試結果:

如上沒法獲取到userName屬性的值,是由於數據庫中的字段爲user_name,而對應到java對象的屬性中爲userName。由於須要在全局配置文件中加入駝峯標示配置(或者經過 sql語句字段起別名方式解決)

<settings>

    <!-- 開啓駝峯映射 -->

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

</settings>

添加日誌支持

1.引入slf依賴

<dependency>

    <groupId>org.slf4j</groupId>

    <artifactId>slf4j-log4j12</artifactId>

    <version>1.6.4</version>

</dependency>

Mybatis學習總結().Mybatis普通方式實現CRUD及動態代理方式實現CRUD

普通方式實現CRUD

user.java

public class User {

private Long id;

// 用戶名

private String userName;

// 密碼

private String password;

// 姓名

private String name;

// 年齡

private Integer age;

// 性別,1男性,2女性

private Integer sex;

// 出生日期

private Date birthday;

// 建立時間

private Date created;

// 更新時間

private Date updated;

//getter and setter

}

定義接口UserDAO.java

public interface UserDAO {

/**

* 根據id查詢用戶數據

*

* @param id

* @return

*/

public User queryUserById(Long id);

/**

* 新增user數據

*

* @param user

*/

public void saveUser(User user);

/**

* 更新user數據

*

* @param user

*/

public void updateUser(User user);

/**

* 根據id刪除用戶數據

*

* @param id

*/

public void deleteUserById(Long id);

}

定義實現類UserDAOImpl.java

public class UserDAOImpl implements UserDAO{

private SqlSessionFactory sqlSessionFactory;

public UserDAOImpl(SqlSessionFactory sqlSessionFactory){

this.sqlSessionFactory = sqlSessionFactory;

}

@Override

public User queryUserById(Long id) {

SqlSession session = this.sqlSessionFactory.openSession();

User user = session.selectOne("userDAO.queryUserById", id);

session.close();

return user;

}

@Override

public void saveUser(User user) {

SqlSession session = this.sqlSessionFactory.openSession();

session.insert("userDAO.saveUser", user);

//提交事物

session.commit();

session.close();

}

@Override

public void updateUser(User user) {

SqlSession session = this.sqlSessionFactory.openSession();

session.update("userDAO.updateUser", user);

//提交事物

session.commit();

session.close();

}

@Override

public void deleteUserById(Long id) {

SqlSession session = this.sqlSessionFactory.openSession();

session.delete("userDAO.deleteUserById", id);

//提交事物

session.commit();

session.close();

}

}

編寫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 namespace="userDAO">

    <select id="queryUserById" resultType="cn.zto.mybatis.pojo.User">

        SELECT *,user_name userName FROM tb_user WHERE id = #{id}

    </select>

    <insert id="saveUser" parameterType="cn.zto.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>

    <update id="updateUser" parameterType="cn.zto.mybatis.pojo.User">

        UPDATE tb_user

        SET

         user_name = #{userName},

         password = #{password},

         name = #{name},

         age = #{age},

         sex = #{sex},

         birthday = #{birthday},

         updated = NOW()

        WHERE

            id = #{id}

    </update>

    <delete id="deleteUserById">

        DELETE FROM tb_user WHERE id = #{id}

    </delete>

</mapper>

定義全局配置文件mybaits-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">

<configuration>

    <!-- 加載配置文件 -->

    <properties resource="jdbc.properties"/>

    <settings>

        <!-- 開啓駝峯映射 -->

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

    </settings>

    <!--

        配置環境,數據庫鏈接

     -->

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

    <mappers>

        <mapper resource="UserDAOMapper.xml" />

    </mappers>

</configuration>

添加Junit依賴,並編寫測試代碼

package cn.zto.mybatis.dao.impl;

import java.io.InputStream;

import java.util.Date;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.junit.Before;

import org.junit.Test;

import cn.zto.mybatis.dao.UserDAO;

import cn.zto.mybatis.dao.impl.UserDAOImpl;

import cn.zto.mybatis.pojo.User;

/**

* @Description: 普通方式實現crud

* @author xingyuchao

* @date 2016年8月2日 下午3:13:00

* @version V1.0

*/

public class UserDAOImplTest {

private UserDAO userDAO;

@Before

public void setUp() throws Exception {

String resource = "mybatis-config.xml";

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

this.userDAO = new UserDAOImpl(sqlSessionFactory);

}

@Test

public void testQueryUserById() {

User user = this.userDAO.queryUserById(2L);

System.out.println(user);

}

@Test

public void testSaveUser() {

User user = new User();

user.setAge(20);

user.setBirthday(new Date());

user.setName("test_1");

user.setPassword("123456");

user.setSex(1);

user.setUserName("test_username_1");

this.userDAO.saveUser(user);

}

@Test

public void testUpdateUser() {

User user = this.userDAO.queryUserById(2L);

user.setAge(40);

this.userDAO.updateUser(user);

}

@Test

public void testDeleteUserById() {

this.userDAO.deleteUserById(5L);

}

}

實現DAO接口中的問題

一、 實現比較繁瑣,接口-->實現類 --> Mapper.xml

二、 實現類中使用Mybatis的方法很是的相似

三、 sql statement 硬編碼到java代碼中。

思考:可否只編寫接口,不寫實現類,編寫Mapper.xml便可?

動態代理方式實現CRUD

流程:

1.mybatis首先讀取全局配置文件mybatis-config.xml

2.加載UserDAO2Mapper.xml,讀到命名空間找到相應的接口,找到接口中的方法名和statement中的id相互對應起來以後,幫咱們生成一個動態代理的實現類,所以咱們就不須要本身手動寫實現類了.

UserDAOImplTest2.java

package cn.zto.mybatis.dao.impl;

import java.io.InputStream;

import java.util.Date;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.junit.Before;

import org.junit.Test;

import cn.zto.mybatis.dao.UserDAO;

import cn.zto.mybatis.pojo.User;

/**

*

* @Description: 動態代理實現類測試用例

* @author xingyuchao

* @date 2016年8月2日 下午3:13:38

* @version V1.0

*/

public class UserDAOImplTest2 {

private UserDAO userDAO;

@Before

public void setUp() throws Exception {

String resource = "mybatis-config.xml";

InputStream inputStream = Resources.getResourceAsStream(resource);

//build方法也能夠配置數據庫鏈接使用哪個

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"test");

//注意:這裏沒有了實現類,須要將事務設置爲自動

SqlSession sqlSession = sqlSessionFactory.openSession(true);

//經過sqlSession獲取到動態代理的實現類

this.userDAO = sqlSession.getMapper(UserDAO.class);

}

@Test

public void testQueryUserById() {

User user = this.userDAO.queryUserById(1L);

System.out.println(user);

}

@Test

public void testSaveUser() {

User user = new User();

user.setAge(20);

user.setBirthday(new Date());

user.setName("test_3");

user.setPassword("123456");

user.setSex(1);

user.setUserName("test_username_3");

this.userDAO.saveUser(user);

}

@Test

public void testUpdateUser() {

User user = this.userDAO.queryUserById(2L);

user.setAge(35);

this.userDAO.updateUser(user);

}

@Test

public void testDeleteUserById() {

this.userDAO.deleteUserById(7L);

}

}

UserDAO2Mapper.xml

Mapper中Namespace的定義自己是沒有限制的,只要不重複便可,可是若是要想使用Mybatis提供的DAO的動態代理,namespace必須爲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="cn.zto.mybatis.dao.UserDAO">

    <select id="queryUserById" resultType="User" parameterType="Long">

        SELECT * FROM tb_user WHERE id = #{id}

    </select>

    <insert id="saveUser" parameterType="cn.zto.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>

    <update id="updateUser" parameterType="cn.zto.mybatis.pojo.User">

        UPDATE tb_user

        SET

         user_name = #{userName},

         password = #{password},

         name = #{name},

         age = #{age},

         sex = #{sex},

         birthday = #{birthday},

         updated = NOW()

        WHERE

            id = #{id}

    </update>

    <delete id="deleteUserById">

        DELETE FROM tb_user WHERE id = #{id}

    </delete>

</mapper>

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">

<configuration>

    <!-- 加載配置文件 -->

    <properties resource="jdbc.properties"/>

    <settings>

        <!-- 開啓駝峯映射 -->

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

    </settings>

    <typeAliases>

        <!-- <typeAlias type="cn.zto.mybatis.pojo.User" alias="User"/> -->

        <!--

            配置掃描包,更適合企業開發

         -->

        <package name="cn.zto.mybatis.pojo" />

    </typeAliases>

    <!--

        配置環境,數據庫鏈接

     -->

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

        <environment id="test">

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

    <mappers>

        <mapper resource="UserDAO2Mapper.xml" />

    </mappers>

</configuration>

其餘的實體等同樣

使用動態代理總結:

使用mapper接口不用寫接口實現類便可完成數據庫操做,使用很是簡單,也是官方所推薦的使用方法。

使用mapper接口的必須具有以幾個條件:

Mapper的namespace必須和mapper接口的全路徑一致。

Mapper接口的方法名必須和sql定義的id一致。

Mapper接口中方法的輸入參數類型必須和sql定義的parameterType一致(parameterType能夠省略)。

Mapper接口中方法的輸出參數類型必須和sql定義的resultType一致。

Mybatis學習總結().Mybatis全局配置文件

Mybatis-Config配置

在config.xml配置文件中的內容和順序以下:

properties 屬性

settings 設置

typeAliases 類型別名

typeHandlers 類型處理器

objectFactory 對象工廠

plugins 插件

environments 環境

environment 環境變量

transactionManager 事務管理器

dataSource 數據源

mappers 映射器

properties屬性

<!-- 加載配置文件 -->

<properties resource="jdbc.properties"/>

這樣引用:

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

setting設置

設置參數

描述

有效值

默認值

cacheEnabled

該配置影響的全部映射器中配置的緩存的全局開關。

true | false

true

lazyLoadingEnabled

延遲加載的全局開關。當開啓時,全部關聯對象都會延遲加載。特定關聯關係中可經過設置fetchType屬性來覆蓋該項的開關狀態。

true | false

false

aggressiveLazyLoading

當啓用時,帶有延遲加載屬性的對象的加載與否徹底取決於對任意延遲屬性的調用;反之,每種屬性將會按需加載。

true | false

true

multipleResultSetsEnabled

是否容許單一語句返回多結果集(須要兼容驅動)。

true | false

true

useColumnLabel

使用列標籤代替列名。不一樣的驅動在這方面會有不一樣的表現,具體可參考相關驅動文檔或經過測試這兩種不一樣的模式來觀察所用驅動的結果。

true | false

true

useGeneratedKeys

容許 JDBC 支持自動生成主鍵,須要驅動兼容。若是設置爲 true 則這個設置強制使用自動生成主鍵,儘管一些驅動不能兼容但仍可正常工做(好比 Derby)。

true | false

False

autoMappingBehavior

指定 MyBatis 是否以及如何自動映射指定的列到字段或屬性。NONE 表示取消自動映射;PARTIAL 只會自動映射沒有定義嵌套結果集映射的結果集。FULL 會自動映射任意複雜的結果集(包括嵌套和其餘狀況)。

NONE, PARTIAL, FULL

PARTIAL

defaultExecutorType

配置默認的執行器。SIMPLE 就是普通的執行器;REUSE 執行器會重用預處理語句(prepared statements);BATCH 執行器將重用語句並執行批量更新。

SIMPLE REUSE BATCH

SIMPLE

defaultStatementTimeout

設置超時時間,它決定驅動等待數據庫響應的秒數。

Any positive integer

Not Set (null)

safeRowBoundsEnabled

容許在嵌套語句中使用行分界(RowBounds)。

true | false

False

mapUnderscoreToCamelCase

是否開啓自動駝峯命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的相似映射。

true | false

False

localCacheScope

MyBatis 利用本地緩存機制(Local Cache)防止循環引用(circular references)和加速重複嵌套查詢。默認值爲 SESSION,這種狀況下會緩存一個會話中執行的全部查詢。若設置值爲 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不一樣調用將不會共享數據。

SESSION | STATEMENT

SESSION

jdbcTypeForNull

當沒有爲參數提供特定的 JDBC 類型時,爲空值指定 JDBC 類型。某些驅動須要指定列的 JDBC 類型,多數狀況直接用通常類型便可,好比 NULLVARCHAR 或 OTHER

JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER

OTHER

lazyLoadTriggerMethods

指定哪一個對象的方法觸發一次延遲加載。

A method name list separated by commas

equals,clone,hashCode,toString

defaultScriptingLanguage

指定動態 SQL 生成的默認語言。

A type alias or fully qualified class name.

org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver

callSettersOnNulls

指定當結果集中值爲 null 的時候是否調用映射對象的 settermap 對象時爲 put)方法,這對於有 Map.keySet() 依賴或 null 值初始化的時候是有用的。注意原始類型(intboolean等)是不能設置成 null 的。

true | false

false

logPrefix

指定 MyBatis 增長到日誌名稱的前綴。

Any String

Not set

logImpl

指定 MyBatis 所用日誌的具體實現,未指定時將自動查找。

SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING

Not set

proxyFactory

 Mybatis 用來建立具備延遲加載能力的對象設置代理工具。

CGLIB | JAVASSIST

CGLIB

mapUnderscoreToCamelCase用法:

<settings>

    <!-- 開啓駝峯映射 -->

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

</settings>

typeAliases 類型別名

類型別名視爲java類型命名一個短的名字,它只和xml配置有關.

<typeAliases>

     <!-- 別名:

     type: 指定java對象類型

     alias: 別名名稱 -->

     <typeAlias type="cn.zto.mybatis.pojo.User" alias="User"/>

</typeAliases>

引用:

<select id="queryUserById" resultType="User" parameterType="Long">

    SELECT * FROM tb_user WHERE id = #{id}

</select>

<typeAliases>

     <!-- 別名:

     type: 指定java對象類型

     alias: 別名名稱 -->

     <!-- <typeAlias type="cn.zto.mybatis.pojo.User" alias="User"/>

     <!--

        配置掃描包,更適合企業開發

        指定掃描包,mybatis會將該包下全部的類生成一個別名

        別名的首字母不區分大小寫,可是,推薦使用大寫.

     -->

     <package name="cn.zto.mybatis.pojo" />

</typeAliases>

引用:

<select id="queryUserById" resultType="User" parameterType="Long">

    SELECT * FROM tb_user WHERE id = #{id}

</select>

Mybatis提供的默認別名:

已經爲普通的 Java 類型內建了許多相應的類型別名。它們都是大小寫不敏感的,須要注意的是因爲重載原始類型的名稱所作的特殊處理。

別名

映射的類型

_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

object

Object

map

Map

hashmap

HashMap

list

List

arraylist

ArrayList

collection

Collection

iterator

Iterator

typeHandlers 類型處理器

類型處理器是在設置參數,以及從Restult中檢索值來匹配java數據類型,Mybatis提供很是多的默認類型處理器,通常狀況下均可以知足平常的使用,不須要自定義處理器。

不經常使用 能夠參考文檔

plugins 插件(攔截器)

MyBatis 容許你在已映射語句執行過程當中的某一點進行攔截調用。默認狀況下,MyBatis 容許使用插件來攔截的方法調用包括:

能夠在一下的幾個點來作攔截。

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 作執行的時候

ParameterHandler (getParameterObject, setParameters) 設置參數的時候

ResultSetHandler (handleResultSets, handleOutputParameters) 結果集的時候

StatementHandler (prepare, parameterize, batch, update, query) 將sql映射成statement對象的時候

自定義攔截器:

environments 環境

MyBatis 能夠配置成適應多種環境,這種機制有助於將 SQL 映射應用於多種數據庫之中,現實狀況下有多種理由須要這麼作。例如,開發、測試和生產環境須要有不一樣的配置;或者共享相同 Schema 的多個生產數據庫,想使用相同的 SQL 映射。

不過要記住:儘管能夠配置多個環境,每一個 SqlSessionFactory 實例只能選擇其一。

因此,若是你想鏈接兩個數據庫,就須要建立兩個 SqlSessionFactory 實例,每一個數據庫對應一個。而若是是三個數據庫,就須要三個實例,依此類推,記起來很簡單:

每一個數據庫對應一個 SqlSessionFactory 實例

<!--

    配置環境,數據庫鏈接

-->

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

    <environment id="test">

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

爲了指定建立哪一種環境,只要將它做爲可選的參數傳遞給 SqlSessionFactoryBuilder 便可。能夠接受環境配置的兩個方法簽名是:

然這種方式也能夠作到很方便的分離多個環境,可是在實際使用場景下咱們都是更多的使用Spring來管理數據源,作環境的分離。

映射器(mappers)

既然 MyBatis 的行爲已經由上述元素配置完了,咱們如今就要定義 SQL 映射語句了。可是首先咱們須要告訴 MyBatis 到哪裏去找到這些語句。Java 在自動查找這方面沒有提供一個很好的方法,因此最佳的方式是告訴 MyBatis 到哪裏去找映射文件。你可使用相對於類路徑的資源引用,或徹底限定資源定位符(包括 file:/// 的 URL),或類名和包名等。例如:

<!-- Using classpath relative resources 路徑相對於資源目錄跟路徑:-->

<mappers>

<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>

<mapper resource="org/mybatis/builder/BlogMapper.xml"/>

<mapper resource="org/mybatis/builder/PostMapper.xml"/>

</mappers>

<!-- Using url fully qualified paths 使用完整的文件路徑:-->

<mappers>

<mapper url="file:///var/mappers/AuthorMapper.xml"/>

<mapper url="file:///var/mappers/BlogMapper.xml"/>

<mapper url="file:///var/mappers/PostMapper.xml"/>

</mappers>

<!-- Using mapper interface classes使用mapper接口類路徑,注意:此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中。-->

<mappers>

<mapper class="org.mybatis.builder.AuthorMapper"/>

<mapper class="org.mybatis.builder.BlogMapper"/>

<mapper class="org.mybatis.builder.PostMapper"/>

</mappers>

<!-- Register all interfaces in a package as mappers 使用Mapper接口掃描包 -->

<mappers>

<package name="org.mybatis.builder"/>

</mappers>

Mybatis學習總結().Mapper映射文件

Mapper映射文件是在實際開發過程當中使用最多的。Mapper文件中包含的元素有:

cache – 配置給定命名空間的緩存。

cache-ref – 從其餘命名空間引用緩存配置。

resultMap – 映射覆雜的結果對象。

sql – 能夠重用的 SQL 塊,也能夠被其餘語句引用。

insert – 映射插入語句

update – 映射更新語句

delete – 映射刪除語句

select – 映射查詢語句

select – 映射查詢語句

<select id="queryUserById" resultType="User" parameterType="Long">

    SELECT * FROM tb_user WHERE id = #{id}

</select>

id:是當前命名空間下的Statement的惟一標識(必須屬性);

parameterType:輸入的參數類型(能夠省略);

resultType:將結果集映射爲的java對象類型(必須屬性);

標籤內部:編寫SQL語句

insert – 映射插入語句

<insert id="saveUser" parameterType="cn.zto.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>

id:是當前命名空間下的Statement的惟一標識(必須屬性);

parameterType:輸入的參數類型(能夠省略);

標籤內部:編寫SQL語句

獲取自增Id

<!-- useGeneratedKeys: 開啓自增id回填

keyColumn: 指定數據庫表中列名

keyProperty: 指定對象的屬性名

若是keyColumn 和 keyProperty 相同,則keyColumn能夠省略不寫 -->

<insert id="saveUser" parameterType="cn.zto.mybatis.pojo.User" useGeneratedKeys="true" keyColumn="id" keyProperty="id">

    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>

@Test

public void testSaveUser() {

User user = new User();

user.setAge(20);

user.setBirthday(new Date());

user.setName("test_3");

user.setPassword("123456");

user.setSex(1);

user.setUserName("test_username_3");

this.userMapper.saveUser(user);

//獲取自增id

System.out.println("id:"+user.getId());

}

update – 映射更新語句

<update id="updateUser" parameterType="cn.zto.mybatis.pojo.User">

    UPDATE tb_user

    SET

     user_name = #{userName},

     password = #{password},

     name = #{name},

     age = #{age},

     sex = #{sex},

     birthday = #{birthday},

     updated = NOW()

    WHERE

        id = #{id}

</update>

id:是當前命名空間下的Statement的惟一標識(必須屬性);

parameterType:輸入的參數類型(能夠省略);

標籤內部:編寫SQL語句

delete – 映射刪除語句

<delete id="deleteUserById">

    DELETE FROM tb_user WHERE id = #{id}

</delete>

id:是當前命名空間下的Statement的惟一標識(必須屬性);

parameterType:輸入的參數類型(能夠省略);

標籤內部:編寫SQL語句

parameterType的傳入參數

傳入類型有三種:

一、簡單類型,string、long、integer等

二、Pojo類型,User等

三、HashMap類型。

在使用#{}傳參時,#{}只是作佔位符,與參數名無關。

在使用${}傳參時,是經過參數名獲取參數的,若是沒有指定參數名則能夠經過value獲取,若是指定則須要按照名稱獲取。

parameterType的傳入多個參數

當Mapper接口中須要傳遞多個參數時有兩種方法傳遞:

使用默認規則獲取參數;

使用@Param註解代表參數傳遞;

其實parameterType參數是能夠省略的

UserMapper.java

package cn.zto.mybatis.mapper;

import cn.zto.mybatis.pojo.User;

public interface UserMapper {

/**

* 模擬登錄

* @Title: login

* @Description: TODO(這裏用一句話描述這個方法的做用)

* @param: @param userName

* @param: @param passwd

* @param: @return

* @return: User

* @throws

*/

public User login(String userName,String passwd);

}

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 namespace="cn.zto.mybatis.mapper.UserMapper">

    <select id="login" resultType="User" >

        SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd}

    </select>

</mapper>

測試

package cn.zto.mybatis.mapper;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.junit.Before;

import org.junit.Test;

import cn.zto.mybatis.pojo.User;

/**

* 動態代理實現類測試用例

*

*/

public class UserMapperTest {

private UserMapper userMapper;

@Before

public void setUp() throws Exception {

String resource = "mybatis-config.xml";

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "test");

SqlSession sqlSession = sqlSessionFactory.openSession(true);

// 經過sqlSession獲取到動態代理的實現類

this.userMapper = sqlSession.getMapper(UserMapper.class);

}

@Test

public void testLogin() {

User user = this.userMapper.login("zhangsan","123");

System.out.println(user);

}

}

結果出錯,錯誤信息參數userName找不到,可用參數爲0,1,param1,param2

修改參數:

<select id="login" resultType="User" >

    <!-- SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd} -->

    SELECT * FROM tb_user WHERE user_name = #{0} and password = #{1}

</select>

或者:

<select id="login" resultType="User" >

    <!-- SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd} -->

    SELECT * FROM tb_user WHERE user_name = #{param1} and password = #{param2}

</select>

測試經過。這種方式爲使用默認規則參數,還有一種是經過@param註解獲取參數

/**

* 模擬登錄

* @Title: login

* @Description: TODO(這裏用一句話描述這個方法的做用)

* @param: @param userName

* @param: @param passwd

* @param: @return

* @return: User

* @throws

*/

public User login(@Param("userName")String userName,@Param("passwd")String passwd);

<select id="login" resultType="User" >

    SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd}

    <!-- SELECT * FROM tb_user WHERE user_name = #{param1} and password = #{param2} -->

</select>

ResultType結果輸出

輸出類型有三種:

簡單類型,string、long、integer等

Pojo類型,User等

HashMap類型。

'#{}'與'${}'的區別

在Mybatis的mapper中,參數傳遞有2種方式,一種是#{}另外一種是${},二者有着很大的區別:

#{} 實現的是sql語句的預處理參數,以後執行sql中用?號代替,使用時不須要關注數據類型,Mybatis自動實現數據類型的轉換。而且能夠防止SQL注入。

${} 實現是sql語句的直接拼接,不作數據類型轉換,須要自行判斷數據類型。不能防止SQL注入。

是否是${}就沒用了呢?不是的,有些狀況下就必須使用${},舉個例子:

在分表存儲的狀況下,咱們從哪張表查詢是不肯定的,也就是說sql語句不能寫死,表名是動態的,查詢條件的固定的,這樣:SELECT * FROM ${tableName} WHERE id = #{id}

CommonMapper.java

package cn.zto.mybatis.mapper;

import java.util.List;

import java.util.Map;

import org.apache.ibatis.annotations.Param;

public interface CommonMapper {

/**

* 根據表名查詢表數據

*

* @param id

* @return

*/

public List<Map<String,Object>> queryByTableName(@Param("tableName")String tableName);

}

CommonMapper.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="cn.zto.mybatis.mapper.CommonMapper">

    <!--SELECT * FROM ${value} ${value}:value是mybatis默認的參數名-->

    <!--在接口中經過@Param來自定義參數名 -->

    <select id="queryByTableName" resultType="HashMap" parameterType="String">

        SELECT * FROM ${tableName}

    </select>

</mapper>

測試

@Test

public void queryByTableName() {

List<Map<String, Object>> queryByTableName = this.commonMapper.queryByTableName("tb_user");

for (Map<String, Object> map : queryByTableName) {

System.out.println(map);

}

}

總結:

#{} 佔位符,用於參數傳遞,和參數名稱無關。

${}用於SQL拼接。

resultMap – 映射覆雜的結果對象

ResultMap是Mybatis中最重要最強大的元素,使用ResultMap能夠解決兩大問題:

POJO屬性名和表結構字段名不一致的問題(有些狀況下也不是標準的駝峯格式)

完成高級查詢,好比說,一對1、一對多、多對多。

解決表字段名和屬性名不一致的問題有兩種方法:

一、若是是駝峯似的命名規則能夠在Mybatis配置文件中設置<setting name="mapUnderscoreToCamelCase" value="true"/>解決

二、使用ResultMap解決。

三、還能夠起別名.

SQL片斷

咱們在java代碼中會將公用的一些代碼提取出來須要的地方直接調用方法便可,在Mybatis也是有相似的概念,那就是SQL片斷。

在Mybatis中使用<sql id="" />標籤訂義SQL片斷,在須要的地方經過<include refid=""/>引用

例如:

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

<select id="queryUserById" resultMap="userResultMap" parameterType="Long">

    SELECT <include refid="userColumns"/> FROM tb_user WHERE id = #{id}

</select>

另一種用法:

將全部的公用的SQL片斷集中定義到一個Mapper.xml文件中,並將此Mapper.xml加入到全局配置文件mybatis-config.xml ,其餘Mapper.xml文件如需引入,經過命名空間.id便可。

<?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="my.common">

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

</mapper>

加入全局配置文件mybatis-config.xml

<mappers>

    <mapper resource="UserMapper.xml" />

    <mapper resource="CommonMapper.xml" />

</mappers>

在mapper映射文件中引用:

<select id="queryUserById" resultMap="userResultMap" parameterType="Long">

    SELECT <include refid="my.common.userColumns"/> FROM tb_user WHERE id = #{id}

</select>

Mybatis學習總結().動態SQLMybatis緩存

MyBatis 的一個強大的特性之一一般是它的動態 SQL 能力。提供了OGNL表達式動態生成SQL的功能。動態SQL有:

一、if

二、choose, when, otherwise

三、where, set

四、foreach

if

需求1:查詢男性用戶,若是輸入了姓名,進行模糊查找。

/**

* 測試動態sql

* 查詢男性用戶,若是輸入了姓名,進行模糊查找。

* @param name

* @return

*/

public List<User> queryUserLikeName(@Param("name") String name);

<select id="queryUserLikeName" resultType="User">

    SELECT * FROM tb_user WHERE sex = 1

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

        AND name LIKE '%${name}%'

    </if>

</select>

測試1:

@Test

public void testQueryUserLikeName(){

List<User> users = this.userMapper.queryUserLikeName("張");

for (User user : users) {

System.out.println(user);

}

}

結果:

測試2:

@Test

public void testQueryUserLikeName(){

List<User> users = this.userMapper.queryUserLikeName(null);

for (User user : users) {

System.out.println(user);

}

}

結果:

choose, when, otherwise

需求2:查詢男性用戶,若是輸入了姓名則按照姓名模糊查找,不然若是輸入了年齡則按照年齡查找。

/**

* 查詢男性用戶,若是輸入了姓名則按照姓名模糊查找,不然若是輸入了年齡則按照年齡查找。

*

* @param name

* @param age

* @return

*/

public List<User> queryUserLikeNameAndAge(@Param("name") String name, @Param("age") Integer age);

<select id="queryUserLikeNameAndAge" resultType="User">

    SELECT * FROM tb_user WHERE sex = 1

    <choose>

        <when test="age !=null and age != ''">

            AND age < #{age}

        </when>

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

            AND name LIKE '%${name}%'

        </when>

    </choose>

</select>

測試:

@Test

public void testQueryUserLikeNameAndAge(){

List<User> users = this.userMapper.queryUserLikeNameAndAge("張",null);

for (User user : users) {

System.out.println(user);

}

}

結果:

where, set

做用:完成WHERE和SET關鍵字,而且處理SQL語句的中語法錯誤。

where測試:

需求3:查詢全部用戶,若是輸入了姓名,進行模糊查找,若是輸入了年齡則按照年齡查找。

/**

* 查詢全部用戶,若是輸入了姓名,進行模糊查找,若是輸入了年齡則按照年齡查找。

*

* @param name

* @return

*/

public List<User> queryUserLikeName2(@Param("name") String name, @Param("age") Integer age);

<select id="queryUserLikeName2" resultType="User">

    SELECT * FROM tb_user

    <where>

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

            AND name LIKE '%${name}%'

        </if>

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

            AND age < #{age}

        </if>

    </where>

</select>

測試:

@Test

public void testQueryUserLikeName2(){

List<User> users = this.userMapper.queryUserLikeName2(null,30);

for (User user : users) {

System.out.println(user);

}

}

結果:

SET測試:

更新數據

/**

* 更新user數據

*

* @param user

*/

public void updateUser2(User user);

<update id="updateUser2" parameterType="cn.zto.mybatis.pojo.User">

    UPDATE tb_user

    <set>

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

            user_name = #{userName},

        </if>

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

            age = #{age},

        </if>

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

            password = #{password},

        </if>

    </set>

    WHERE

        id = #{id}

</update>

測試:

@Test

public void testUpdateUser2() {

User user = this.userMapper.queryUserById(2L);

user.setAge(35);

user.setPassword(null);

this.userMapper.updateUser2(user);

}

結果:

foreach

需求4:按照多個ID查詢用戶信息。

/**

* 按照多個ID查詢用戶信息。

*

* @param name

* @return

*/

public List<User> queryUserByIds(@Param("ids") List<Long> ids);

<select id="queryUserByIds" resultType="User">

    SELECT * FROM tb_user WHERE id IN

    <foreach collection="ids" item="id" open="(" close=")" separator=",">

        #{id}

    </foreach>

</select>

測試:

@Test

public void testQueryUserByIds(){

List<Long> ids = new ArrayList<Long>();

ids.add(1L);

ids.add(2L);

ids.add(3L);

List<User> users = this.userMapper.queryUserByIds(ids);

for (User user : users) {

System.out.println(user);

}

}

結果:

緩存:一級緩存

Mybatis的一級緩存的做用域是session,當openSession()後,若是執行相同的SQL(相同語句和參數),Mybatis不進行執行SQL,而是從緩存中命中返回。

原理:

Mybatis執行查詢時首先去緩存區命中,若是命中直接返回,沒有命中則執行SQL,從數據庫中查詢。

在Mybatis中一級緩存是默認開啓,而且沒法關閉。

測試一級緩存:

一級緩存知足條件:

一、 同一個session中

二、 相同的SQL和參數

使用session.clearCache()強制查詢不緩存。

在執行insert、update、delete時會刷新緩存。

緩存:二級緩存

Mybatis的二級緩存的做用域是一個mapper的namespace,同一個namespace中查詢sql能夠從緩存中命中。

二級緩存是能夠跨session的。

開啓二級緩存:

在mapper.xml文件中加入 <cache /> 。

注意:在Mybatis-Config中有緩存的全局控制器(cacheEnabled),默認是開啓的,因此無需手動開啓。

也能夠手動關閉二級緩存:

二級緩存關閉後,上面測試第二次查詢將從數據庫查詢

在<cache />標籤中還有其餘一些參數,以下:

能夠參考mybatis官方文檔

Mybatis學習總結().Mybatis高級查詢及延遲加載

 

Mybatis做爲一個ORM框架,也對SQL的高級查詢作了支持,下面咱們學習Mybatis下的一對1、一對多、多對多的查詢。

 

案例說明:
此案例的業務關係是用戶、訂單、訂單詳情、商品之間的關係,其中,
一個訂單隻能屬於一我的。
一個訂單能夠有多個訂單詳情。
一個訂單詳情中包含一個商品信息。
 
它們的關係是:
 
訂單和人是 一對一的關係。
訂單和訂單詳情是 一對多 的關係。

訂單和商品是 多對多的關係。

 

數據庫關係圖:


 

 

一對一查詢

需求:一對一查詢:查詢訂單,而且查詢出下單人的信息。

 

SQL:   SELECT  o.*, u.user_name,u. NAME FROM tb_order o LEFT JOIN tb_user u ON o.user_id = u.id WHERE order_number = '20140921001'

第一種實現:

User.java

 

 

 

package cn.zto.mybatis.pojo;

 

 

import java.util.Date;

 

 

/**

 

 

*

 

 

* @ClassName: User

 

 

* @Description:對應用戶表

 

 

* @author: xyc

 

 

* @date: 2017年2月11日 下午8:11:13

 

 

*

 

 

*/

 

 

public class User implements java.io.Serializable{

 

 

private static final long serialVersionUID = 1L;

 

 

private Long id;

 

 

// 用戶名

 

 

private String userName;

 

 

// 密碼

 

 

private String password;

 

 

// 姓名

 

 

private String name;

 

 

// 年齡

 

 

private Integer age;

 

 

// 性別,1男性,2女性

 

 

private Integer sex;

 

 

// 出生日期

 

 

private Date birthday;

 

 

// 建立時間

 

 

private Date created;

 

 

// 更新時間

 

 

private Date updated;

 

 

//getter And setter

 

 

@Override

 

 

public String toString() {

 

 

return "User [id=" + id + ", userName=" + userName + ", password=" + password + ", name=" + name

 

 

+ ", age=" + age + ", sex=" + sex + ", birthday=" + birthday + ", created=" + created

 

 

+ ", updated=" + updated + "]";

 

 

}

 

 

}

 


Order.java

 

 

 

 

package cn.zto.mybatis.pojo;

 

 

/**

 

 

*

 

 

* @ClassName: Order

 

 

* @Description:對應訂單表

 

 

* @author: xyc

 

 

* @date: 2017年2月11日 下午8:22:24

 

 

*

 

 

*/

 

 

public class Order {

 

 

private Integer id;

 

 

private Long userId;

 

 

private String orderNumber;

 

 

//getter And setter

 

 

@Override

 

 

public String toString() {

 

 

return "Order [id=" + id + ", userId=" + userId + ", orderNumber=" + orderNumber + "]";

 

 

}

 

 

}

 

OrderUser.java

 

 

 

 

package cn.zto.mybatis.pojo;

 

 

/**

 

 

*

 

 

* @ClassName: OrderUser

 

 

* @Description: 此類用於補字段

 

 

* @author: xyc

 

 

* @date: 2017年2月11日 下午8:24:51

 

 

*

 

 

*/

 

 

public class OrderUser extends Order{

 

 

private String userName;

 

 

private String name;

 

 

//getter and setter

 

 

@Override

 

 

public String toString() {

 

 

return "OrderUser [userName=" + userName + ", name=" + name + "]";

 

 

}

 

 

}

 

 

OrderMapper.java

 

 

package cn.zto.mybatis.mapper;

 

 

import cn.zto.mybatis.pojo.OrderUser;

 

 

/**

 

 

 

* 測試高級查詢

 

 

 

*/

 

 

 

public interface OrderMapper {

 

 

 

/**

 

 

 

* 查詢訂單,而且查詢出下單人的信息。

 

 

 

* @param orderNumber

 

 

 

* @return

 

 

 

*/

 

 

 

public OrderUser queryOrderAndUserByOrderNumber(String orderNumber);

 

 

 

}

 

 


OrderMapper.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="cn.zto.mybatis.mapper.OrderMapper">

 

 

<select id="queryOrderAndUserByOrderNumber" resultType="OrderUser">

 

 

SELECT

 

 

o.*,

 

 

u.user_name,

 

 

u.name

 

 

FROM

 

 

tb_order o

 

 

LEFT JOIN tb_user u ON o.user_id = u.id

 

 

WHERE order_number = #{orderNumber}

 

 

</select>

 

 

</mapper>

 

記得加入到全局配置文件中:

 

測試結果:



第二種實現:

核心思想:面向對象的思想,在Order對象中添加User對象。

 

 

 

package cn.zto.mybatis.pojo;

 

 

/**

 

 

*

 

 

* @ClassName: Order

 

 

* @Description:對應訂單表

 

 

* @author: xyc

 

 

* @date: 2017年2月11日 下午8:33:12

 

 

*

 

 

*/

 

 

public class Order {

 

 

private Integer id;

 

 

private Long userId;

 

 

private String orderNumber;

 

 

private User user;

 

 

//getter And setter

 

 

}

 


Mapper接口:

 

 

 

 

/**

 

 

* 查詢訂單,而且查詢出下單人的信息。

 

 

* @param orderNumber

 

 

* @return

 

 

*/

 

 

public Order queryOrderAndUserByOrderNumber2(String orderNumber);

 


Mapper映射文件

 

 

 

<!-- 在resultMap中,完成對象映射時,autoMapping默認爲false,所以這裏須要打開,不然有的屬性關係沒法對應 -->

 

 

<resultMap type="Order" id="orderResultMap" autoMapping="true">

 

 

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

 

 

<!--

 

association:用戶映射java對象

property: 對象中的屬性名稱

javaType:對象中的屬性的類型 --><association property="user" javaType="User" autoMapping="true"><id column="user_id" property="id"/></association></resultMap>

<!-- 使用resultType不能完成自動映射,因此須要手動完成結果集的映射,須要使用resultMap實現。-->

<select id="queryOrderAndUserByOrderNumber2" resultMap="orderResultMap">SELECTo.*,u.user_name, u.nameFROMtb_order oLEFT JOIN tb_user u ON o.user_id = u.idWHERE order_number = #{orderNumber}</select>

 

測試:

 

 

 

 

 

 

 

@Test

 

 

public void testQueryOrderAndUserByOrderNumber2() {

 

 

Order order = this.orderMapper.queryOrderAndUserByOrderNumber2("20140921001");

 

 

System.out.println(order);

 

 

}

 

結果:

 




一對多查詢

需求:查詢訂單,查詢出下單人信息而且查詢出訂單詳情。
 
SQL:

 

 

SELECT

 

 

o.*,

 

 

u.user_name,

 

 

u.name,

 

 

od.id detail_id,

 

 

od.item_id,

 

 

od.total_price

 

 

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 order_number = '20140921001'

 

 
Order.java

 

 

package cn.zto.mybatis.pojo;

 

 

import java.util.List;

 

 

/**

 

 

* 訂單表

 

 

*

 

 

*/

 

 

public class Order {

 

 

private Integer id;

 

 

private Long userId;

 

 

private String orderNumber;

 

 

private User user;

 

 

//映射一對多查詢的訂單詳情

 

 

private List<Orderdetail> orderdetails;

 

 

//getter And setter

 

 

@Override

 

 

public String toString() {

 

 

return "Order [id=" + id + ", userId=" + userId + ", orderNumber=" + orderNumber + ", user=" + user

 

 

+ ", orderdetails=" + orderdetails + "]";

 

 

}

 

 

}

 

Orderdetail.java

 

package cn.zto.mybatis.pojo;

 

 

/**

 

 

*

 

 

* @ClassName: Orderdetail

 

 

* @Description:訂單詳情

 

 

* @author: xyc

 

 

* @date: 2017年2月11日 下午9:42:28

 

 

*

 

 

*/

 

 

public class Orderdetail {

 

 

private Integer id;

 

 

private Double totalPrice;

 

 

private Integer status;

 

 

private Integer itemId;

 

 

private Item item;

 

 

//getter and setter

 

}

接口:

 

 

/**

 

 

* 查詢訂單,查詢出下單人信息而且查詢出訂單詳情。

 

 

*

 

 

* @param orderNumber

 

 

* @return

 

 

*/

 

 

public Order queryOrderAndUserAndOrderDetailByOrderNumber(String orderNumber);

 

 
Mapper映射文件:

 

 

<resultMap type="Order" id="orderUserOrderDetailresultMap" autoMapping="true">

 

 

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

 

 

<!--

 

 

association:映射java對象

 

 

property: 對象中的屬性名稱

 

 

javaType:對象中的屬性的類型

 

 

-->

 

 

<association property="user" javaType="User" autoMapping="true">

 

 

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

 

 

</association>

 

 

<!--

 

 

collection:映射集合

 

 

javaType: 屬性的java類型

 

 

ofType:集合中的對象的java類型

 

 

-->

 

 

<collection property="orderdetails" javaType="List" ofType="Orderdetail" autoMapping="true">

 

 

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

 

 

</collection>

 

 

</resultMap>

 

 

<select id="queryOrderAndUserAndOrderDetailByOrderNumber" resultMap="orderUserOrderDetailresultMap">

 

 

SELECT

 

 

o.*,

 

 

u.user_name,

 

 

u.name,

 

 

od.id detail_id,

 

 

od.item_id,

 

 

od.total_price

 

 

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 order_number = #{orderNumber}

 

 

</select>

 


測試:

 

 

@Test

 

 

public void testQueryOrderAndUserAndOrderDetailByOrderNumber() {

 

 

Order order = this.orderMapper.queryOrderAndUserAndOrderDetailByOrderNumber("20140921001");

 

 

System.out.println(order);

 

 

}

 

結果:
 

多對多查詢

需求:查詢訂單,查詢出下單人信息而且查詢出訂單詳情中的商品數據
 
SQL:
 

SELECT

o.*,
u.user_name,

u.name,

od.id detail_id,

od.item_id,

od.total_price,

i.item_name,

i.item_price,

i.item_detail

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 order_number = '20140921001'


Item.java
 

package cn.zto.mybatis.pojo;

/**

* 商品表

*/

public class Item {

private Integer id;

private String itemName;

private Float itemPrice;

private String itemDetail;

//getter and setter

}


Orderdetail.java

 

package cn.zto.mybatis.pojo;

/**
*
* @ClassName: Orderdetail
* @Description:訂單詳情
* @author: xyc
* @date: 2017年2月11日 下午9:42:28
*
*/
public class Orderdetail {
private Integer id;
private Double totalPrice;
private Integer status;
private Integer itemId;
private Item item;
//gette and setter
}


接口:

 

/**

* 多對多查詢

* 查詢訂單,查詢出下單人信息而且查詢出訂單詳情中的商品數據。

* @param orderNumber

* @return

*/

public Order queryOrderAndUserAndOrderDetailAndItemByOrderNumber(String orderNumber);



Mapper映射:

 

<resultMap type="Order" id="orderUserOrderDetailItemResultMap" autoMapping="true">

<id column="id" property="id"/>
<!--
property: 對象中的屬性名稱
javaType:對象中的屬性的類型
-->
<association property="user" javaType="User" autoMapping="true">
<id column="user_id" property="id"/>
</association>
<!-- 映射orderdetails -->
<collection property="orderdetails" javaType="List" ofType="Orderdetail" autoMapping="true">
<id property="id" column="detail_id"/>
<!--
映射Orderdetail中的Item對象
-->
<association property="item" javaType="Item" autoMapping="true">
<id property="id" column="item_id"/>
</association>
</collection>
</resultMap>
<select id="queryOrderAndUserAndOrderDetailAndItemByOrderNumber" resultMap="orderUserOrderDetailItemResultMap">
SELECT
o.*,
u.user_name,
u.name,
od.id detail_id,
od.item_id,
od.total_price,
i.item_name,
i.item_price,
i.item_detail
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 order_number = #{orderNumber}
</select>


測試:

 

@Test

public void testQueryOrderAndUserAndOrderDetailAndItemByOrderNumber() {
Order order = this.orderMapper.queryOrderAndUserAndOrderDetailAndItemByOrderNumber("20140921001");

System.out.println(order);

}


結果:


ResultMap的繼承  

經過上述能夠發現,下面代碼重用了,如何解決呢?

 

<!-- 在resultMap中,完成對象映射時,autoMapping默認爲false,所以這裏須要打開,不然有的屬性關係沒法對應 -->

<resultMap type="Order" id="orderResultMap" autoMapping="true">

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

<!--

property: 對象中的屬性名稱

javaType:對象中的屬性的類型

-->

<association property="user" javaType="User" autoMapping="true">

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

</association>

</resultMap>


咱們能夠經過繼承來完善

 

<resultMap type="Order" id="orderUserOrderDetailItemResultMap" extends="orderResultMap" autoMapping="true">

<!-- 映射orderdetails -->

<collection property="orderdetails" javaType="List" ofType="Orderdetail" autoMapping="true">

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

<!--

映射Orderdetail中的Item對象

-->

<association property="item" javaType="Item" autoMapping="true">

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

</association>

</collection>

</resultMap>


extends的值爲上面resultMap的id.

 

 

延遲加載

延遲加載的意義在於,雖然是關聯查詢,但不是及時將關聯的數據查詢出來,並且在須要的時候進行查詢。


開啓延遲加載:
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>


lazyLoadingEnabled:true使用延遲加載,false禁用延遲加載。默認爲true
aggressiveLazyLoading:true啓用時,當延遲加載開啓時訪問對象中一個懶對象屬性時,將徹底加載這個對象的全部懶對象屬性。false,當延遲加載時,按需加載對象屬性(即訪問對象中一個懶對象屬性,不會加載對象中其餘的懶對象屬性)。默認爲true

 

①. 添加cglib支持

 

 

<dependency>

<groupId>cglib</groupId>

<artifactId>cglib</artifactId>

<version>3.1</version>

</dependency>

 

 

②.全局配置文件中開啓延遲加載

 

 

<settings>

<!-- 開啓駝峯映射 -->

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

<!-- 二級緩存的全局開關 -->

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

<!-- 延遲加載的開關 -->

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

<!--

true啓用時,當延遲加載開啓時訪問對象中一個懶對象屬性時,將徹底加載這個對象的全部懶對象屬性。

false,當延遲加載時,按需加載對象屬性(即訪問對象中一個懶對象屬性,不會加載對象中其餘的懶對象屬性)

-->

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

</settings>

 

 

③.編寫接口:

 

 

/**

* 測試延遲加載
* 查詢訂單,而且查詢出下單人的信息。
* @param orderNumber
* @return
*/

 

public Order lazyQueryOrderAndUserByOrderNumber(String orderNumber);


④.編寫Mapper.xml

 


⑤.測試:

 

 

@Test

public void testLazyQueryOrderAndUserByOrderNumber() {
Order order = this.orderMapper.lazyQueryOrderAndUserByOrderNumber("20140921001");

User user = order.getUser();//觸發延遲加載

System.out.println(user);

System.out.println(order);

}


結果:

 

Mybatis學習總結(七).Mybatis插件之分頁插件

 

Mybatis的plugin實現原理

 
下圖黑色部分爲以前方式,紅色部分爲使用插件後
 

實現通用分頁組件

若是想要將現有的select語句改成支持分頁功能的查詢語句該怎麼作呢?最簡單的一種作法就是將全部的select語句都加上limit來實現分頁,這種作法有什麼問題呢?


一、要改動的地方很是多,並且每一個sql改動邏輯基本上一致;
二、DAO層的查詢邏輯要改動,要在原來查詢以後執行查詢 SELECT count(1) from ….. 查詢數據總條數。


有沒有一種簡便方法實現呢?

Mybatis提供了plugin機制,容許咱們在Mybatis的原有處理流程上加入本身邏輯,全部咱們就可使用這種邏輯加上咱們的分頁邏輯,也就是實現攔截器。

Mybatis支持的攔截的接口有4個, Executor、ParameterHandler、ResultSetHandler、StatementHandler。
 


使用PageHelper實現分頁

 
PageHelper實現了通用的分頁查詢,其支持的數據有,mysql、Oracle、DB二、PostgreSQL等主流的數據庫。
該插件託管於github: https://github.com/pagehelper/Mybatis-PageHelper


參考《 Mybatis分頁插件 - PageHelper.docx 》
 
①.導入依賴

 

<dependency>

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

<artifactId>pagehelper</artifactId>

<version>3.4.2</version>

</dependency>

<dependency>

<groupId>com.github.jsqlparser</groupId>

<artifactId>jsqlparser</artifactId>

<version>0.9.1</version>

</dependency>


②.在全局配置文件中配置插件

 

 

<plugins>

<!-- com.github.pagehelper爲PageHelper類所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 方言 -->
<property name="dialect" value="mysql"/>
<!-- 該參數默認爲false -->
<!-- 設置爲true時,使用RowBounds分頁會進行count查詢 -->
<property name="rowBoundsWithCount" value="true"/>
</plugin>
</plugins>



③.編寫接口

public List<User> queryUserListLikeName(@Param("name") String name);


④.編寫映射文件

 

<select id="queryUserListLikeName" parameterType="String" resultType="User">

SELECT <include refid="my.common.userColumns"/> FROM tb_user WHERE name LIKE '%${name}%'

</select>


⑤.測試分頁

 

@Test

public void testQueryUserListLikeName() {
//設置分頁條件,Parameters:pageNum 頁碼pageSize 每頁顯示數量count 是否進行count查詢
PageHelper.startPage( 1, 3, true);
List<User> users = this.userMapper.queryUserListLikeName(null);
for (User user : users) {
System.out.println(user);
}
}


結果:

 
 
可使用PageInfo 查看分頁信息
 

@Test

public void testQueryUserListLikeName() {
//設置分頁條件,Parameters:pageNum 頁碼pageSize 每頁顯示數量count 是否進行count查詢

PageHelper.startPage(1, 3, true);

List<User> users = this.userMapper.queryUserListLikeName(null);

PageInfo<User> pageInfo = new PageInfo<User>(users);

//打印分頁信息

System.out.println("數據總數:" + pageInfo.getTotal());

System.out.println("數據總頁數:" + pageInfo.getPages());

System.out.println("最後一頁:" + pageInfo.getLastPage());

for (User user : pageInfo.getList()) {

System.out.println(user);

}

}


PageInfo的方法
 
 
Mybatis批量增刪改
 
批量刪除
 
批量增長
 
批量修改

 

Mybatis和Spring的整合

目錄結構:

 

①.引入依賴pom.xml

 

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

 

<modelVersion>4.0.0</modelVersion>

 

<parent>

 

<groupId>cn.zto.parent</groupId>

 

<artifactId>zto-parent</artifactId>

 

<version>0.0.1-SNAPSHOT</version>

 

</parent>

 

<groupId>cn.zto.mybatis</groupId>

 

<artifactId>zto-mybatis-spring</artifactId>

 

<version>1.0.0-SNAPSHOT</version>

 

<dependencies>

 

<!-- 單元測試 -->

 

<dependency>

 

<groupId>junit</groupId>

 

<artifactId>junit</artifactId>

 

<scope>test</scope>

 

</dependency>

 

<!-- Mybatis -->

 

<dependency>

 

<groupId>org.mybatis</groupId>

 

<artifactId>mybatis</artifactId>

 

</dependency>

 

<!-- MySql -->

 

<dependency>

 

<groupId>mysql</groupId>

 

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

 

</dependency>

 

<dependency>

 

<groupId>org.slf4j</groupId>

 

<artifactId>slf4j-log4j12</artifactId>

 

</dependency>

 

<dependency>

 

<groupId>cglib</groupId>

 

<artifactId>cglib</artifactId>

 

<version>3.1</version>

 

</dependency>

 

<dependency>

 

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

 

<artifactId>pagehelper</artifactId>

 

<version>3.7.5</version>

 

</dependency>

 

<dependency>

 

<groupId>com.github.jsqlparser</groupId>

 

<artifactId>jsqlparser</artifactId>

 

<version>0.9.1</version>

 

</dependency>

 

<!-- 整合 -->

 

<dependency>

 

<groupId>org.springframework</groupId>

 

<artifactId>spring-context</artifactId>

 

</dependency>

 

<dependency>

 

<groupId>org.mybatis</groupId>

 

<artifactId>mybatis-spring</artifactId>

 

</dependency>

 

<!-- 鏈接池 -->

 

<dependency>

 

<groupId>com.jolbox</groupId>

 

<artifactId>bonecp-spring</artifactId>

 

<version>0.8.0.RELEASE</version>

 

</dependency>

 

<dependency>

 

<groupId>org.springframework</groupId>

 

<artifactId>spring-jdbc</artifactId>

 

</dependency>

 

<dependency>

 

<groupId>org.springframework</groupId>

 

<artifactId>spring-aspects</artifactId>

 

</dependency>

 

</dependencies>

 

</project>

②.編寫實體User、Mapper接口、Mapper映射文件

 

User.java

 

 

 

package cn.zto.mybatis.pojo;

 

import java.util.Date;

 

public class User implements java.io.Serializable{

 

private static final long serialVersionUID = -5846970261372764303L;

 

private Long id;

 

// 用戶名

 

private String userName;

 

// 密碼

 

private String password;

 

// 姓名

 

private String name;

 

// 年齡

 

private Integer age;

 

// 性別,1男性,2女性

 

private Integer sex;

 

// 出生日期

 

private Date birthday;

 

// 建立時間

 

private Date created;

 

// 更新時間

 

private Date updated;

 

//getter and setter

 

@Override

 

public String toString() {

 

return "User [id=" + id + ", userName=" + userName + ", password=" + password + ", name=" + name

 

+ ", age=" + age + ", sex=" + sex + ", birthday=" + birthday + ", created=" + created

 

+ ", updated=" + updated + "]";

 

}

 

}

 

UserMapper.java

 

 

 

package cn.zto.mybatis.mapper;

 

import org.apache.ibatis.annotations.Param;

 

import cn.zto.mybatis.pojo.User;

 

public interface UserMapper {

 

/**

 

* 根據id查詢用戶信息

 

*

 

* @param id

 

* @return

 

*/

 

public User queryUserById(@Param("id") Long id);

 

}

 

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 namespace="cn.zto.mybatis.mapper.UserMapper">

 

<select id="queryUserById" parameterType="Long" resultType="User">

 

SELECT * FROM tb_user WHERE id = #{id}

 

</select>

 

</mapper>

 

③.配置數據源

 

jdbc.properties

 

 

jdbc.driver=com.mysql.jdbc.Driver

 

jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true

 

jdbc.username=root

 

jdbc.password=123456

 

 

applicationContext.xml

 

 

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

 

<beans xmlns="http://www.springframework.org/schema/beans"

 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

 

xmlns:context="http://www.springframework.org/schema/context"

 

xmlns:mvc="http://www.springframework.org/schema/mvc"

 

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

 

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

 

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 

<!-- 使用spring自帶的佔位符替換功能 -->

 

<bean

 

class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

 

<!-- 容許JVM參數覆蓋 -->

 

<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />

 

<!-- 忽略沒有找到的資源文件 -->

 

<property name="ignoreResourceNotFound" value="true" />

 

<!-- 配置資源文件 -->

 

<property name="locations">

 

<list>

 

<value>classpath:jdbc.properties</value>

 

</list>

 

</property>

 

</bean>

 

<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"

 

destroy-method="close">

 

<!-- 數據庫驅動 -->

 

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

 

<!-- 相應驅動的jdbcUrl -->

 

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

 

<!-- 數據庫的用戶名 -->

 

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

 

<!-- 數據庫的密碼 -->

 

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

 

<!-- 檢查數據庫鏈接池中空閒鏈接的間隔時間,單位是分,默認值:240,若是要取消則設置爲0 -->

 

<property name="idleConnectionTestPeriod" value="60" />

 

<!-- 鏈接池中未使用的連接最大存活時間,單位是分,默認值:60,若是要永遠存活設置爲0 -->

 

<property name="idleMaxAge" value="30" />

 

<!-- 每一個分區最大的鏈接數 -->

 

<property name="maxConnectionsPerPartition" value="150" />

 

<!-- 每一個分區最小的鏈接數 -->

 

<property name="minConnectionsPerPartition" value="5" />

 

</bean>

 

</beans>

 

④.配置SqlSessionFactory

這裏使用的並非SqlSessionFactoryBuilder,而是使用的Mybatis-spring整合jar中的org.mybatis.spring.SqlSessionFactoryBean,而且經過configLocation配置Mybatis的配置文件。

 

 

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

 

<beans xmlns="http://www.springframework.org/schema/beans"

 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

 

xmlns:context="http://www.springframework.org/schema/context"

 

xmlns:mvc="http://www.springframework.org/schema/mvc"

 

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

 

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

 

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 

<!-- 定義Mybatis的SqlSessionFactory -->

 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 

<!-- 定義數據源 -->

 

<property name="dataSource" ref="dataSource" />

 

<!-- 指定mybatis全局配置文件 -->

 

<property name="configLocation" value="classpath:mybatis-config.xml"></property>

 

</bean>

 

</beans>

 

⑤.配置mybatis全局文件

 

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">

 

<configuration>

 

<settings>

 

<!-- 開啓駝峯映射 -->

 

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

 

</settings>

 

<typeAliases>

 

<!-- <typeAlias type="cn.zto.mybatis.pojo.User" alias="User"/> -->

 

<!--

 

配置掃描包,更適合企業開發

 

-->

 

<package name="cn.zto.mybatis.pojo"/>

 

</typeAliases>

 

<mappers>

 

<mapper resource="UserMapper.xml" />

 

</mappers>

 

</configuration>

 

⑥.添加日誌

log4j.properties

 

 

log4j.rootLogger=DEBUG,A1

 

log4j.logger.org.mybatis = DEBUG

 

log4j.appender.A1=org.apache.log4j.ConsoleAppender

 

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

 

log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

 

 

⑦.測試:

 

 

package cn.zto.mybatis.mapper;

 

import org.apache.ibatis.session.SqlSession;

 

import org.apache.ibatis.session.SqlSessionFactory;

 

import org.junit.Before;

 

import org.junit.Test;

 

import org.springframework.context.ApplicationContext;

 

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import cn.zto.mybatis.pojo.User;

 

public class UserMapperTest {

 

private UserMapper userMapper;

 

/**

 

* @throws Exception

 

*/

 

@Before

 

public void setUp() throws Exception {

 

// 初始化SPring容器

 

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml",

 

"applicationContext-mybatis.xml");

 

// 從容器中獲取SqlSessionFactory

 

SqlSessionFactory sqlSessionFactory = applicationContext.getBean(SqlSessionFactory.class);

 

SqlSession sqlSession = sqlSessionFactory.openSession(true);

 

this.userMapper = sqlSession.getMapper(UserMapper.class);

 

}

 

@Test

 

public void testQueryUserById() {

 

User user = this.userMapper.queryUserById(1L);

 

System.out.println(user);

 

}

 

}

 

結果:

 

 

ok,mybatis已經和spring整合起來了。

可是發現 每次仍是要先獲取SqlSessionFactory,而後獲取到session,以後從session中獲取Mapper

若是能從容器中直接獲取到Mapper就更好了

 

定義Mapper

在applicationContext-mybatis.xml中添加

 

 

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

 

<beans xmlns="http://www.springframework.org/schema/beans"

 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

 

xmlns:context="http://www.springframework.org/schema/context"

 

xmlns:mvc="http://www.springframework.org/schema/mvc"

 

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

 

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

 

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 

<!-- 定義Mybatis的SqlSessionFactory -->

 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 

<!-- 定義數據源 -->

 

<property name="dataSource" ref="dataSource" />

 

<!-- 指定mybatis全局配置文件 -->

 

<property name="configLocation" value="classpath:mybatis-config.xml"></property>

 

</bean>

 

<!-- 定義Mapper -->

 

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">

 

<!-- 指定Mapper接口的地址 -->

 

<property name="mapperInterface" value="cn.zto.mybatis.mapper.UserMapper" />

 

<!-- sqlSessionFactory依賴 -->

 

<property name="sqlSessionFactory" ref="sqlSessionFactory" />

 

</bean>

 

</beans>



 

 

測試:

 

 

package cn.zto.mybatis.mapper;

 

import org.junit.Before;

 

import org.junit.Test;

 

import org.springframework.context.ApplicationContext;

 

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import cn.zto.mybatis.pojo.User;

 

public class UserMapperTest {

 

private UserMapper userMapper;

 

/**

 

* @throws Exception

 

*/

 

@Before

 

public void setUp() throws Exception {

 

// 初始化SPring容器

 

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml",

 

"applicationContext-mybatis.xml");

 

// 從容器中獲取SqlSessionFactory

 

// SqlSessionFactory sqlSessionFactory =

 

// applicationContext.getBean(SqlSessionFactory.class);

 

// SqlSession sqlSession = sqlSessionFactory.openSession(true);

 

// this.userMapper = sqlSession.getMapper(UserMapper.class);

 

this.userMapper = applicationContext.getBean(UserMapper.class);

 

}

 

@Test

 

public void testQueryUserById() {

 

User user = this.userMapper.queryUserById(1L);

 

System.out.println(user);

 

}

 

}

 

上面仍是有點問題,若是有多個Mapper映射文件,是否是要配置多個MapperFactotyBean呢?

 

這裏能夠配置Mapper接口的自動掃描器

配置Mapper接口的自動掃描器

咱們沒有必要一個一個的在spring配置文件中配置Mapper接口,Mybatis的Spring整合包中提供了更高級的方式,mapper接口掃描器,org.mybatis.spring.mapper.MapperScannerConfigurer

在applicationContext-mybatis.xml中添加

 

 

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

 

<beans xmlns="http://www.springframework.org/schema/beans"

 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

 

xmlns:context="http://www.springframework.org/schema/context"

 

xmlns:mvc="http://www.springframework.org/schema/mvc"

 

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

 

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

 

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 

<!-- 定義Mybatis的SqlSessionFactory -->

 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 

<!-- 定義數據源 -->

 

<property name="dataSource" ref="dataSource" />

 

<!-- 指定mybatis全局配置文件 -->

 

<property name="configLocation" value="classpath:mybatis-config.xml"></property>

 

</bean>

 

<!-- 定義Mapper -->

 

<!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">

 

指定Mapper接口的地址

 

<property name="mapperInterface" value="cn.zto.mybatis.mapper.UserMapper" />

 

sqlSessionFactory依賴

 

<property name="sqlSessionFactory" ref="sqlSessionFactory" />

 

</bean> -->

 

<!-- 定義Mapper接口掃描器 -->

 

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

 

<property name="basePackage" value="cn.zto.mybatis.mapper" />

 

</bean>

 

</beans>

 

問題?多個包怎麼配置?

 

參考源碼能夠用分隔符分割

 

 

使用通配符配置mapper.xml文件

 

 

<!-- 定義Mybatis的SqlSessionFactory -->

 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 

<!-- 定義數據源 -->

 

<property name="dataSource" ref="dataSource" />

 

<!-- 指定mybatis全局配置文件 -->

 

<property name="configLocation" value="classpath:mybatis-config.xml"></property>

 

<!-- 掃描mappers目錄以及子目錄下的全部xml文件 -->

 

<property name="mapperLocations" value="classpath:mappers/**/*.xml" />

 

</bean>

 

使用mapperLocations掃描到mapper文件下的全部xml,同時移除mybatis全局配置文件中的mapper配置

 

 

繼續簡化Mybatis全局配置文件,將別名包配置到也配置到spring中,同時將全局配置文件中的別名配置移除

 

 

<!-- 定義Mybatis的SqlSessionFactory -->

 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 

<!-- 定義數據源 -->

 

<property name="dataSource" ref="dataSource" />

 

<!-- 指定mybatis全局配置文件 -->

 

<property name="configLocation" value="classpath:mybatis-config.xml"></property>

 

<!-- 掃描mappers目錄以及子目錄下的全部xml文件 -->

 

<property name="mapperLocations" value="classpath:mappers/**/*.xml" />

 

<!-- 別名掃描包 -->

 

<property name="typeAliasesPackage" value="cn.zto.mybatis.pojo"/>

 

</bean>

 

最終mybatis全局配置文件下剩下駝峯配置了

 

 

 

<?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">

 

<configuration>

 

<settings>

 

<!-- 開啓駝峯映射 -->

 

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

 

</settings>

 

<!-- <typeAliases>

 

<typeAlias type="cn.zto.mybatis.pojo.User" alias="User"/>

 

配置掃描包,更適合企業開發

 

<package name="cn.zto.mybatis.pojo"/>

 

</typeAliases> -->

 

<!-- <mappers>

 

<mapper resource="UserMapper.xml" />

 

</mappers> -->

 

</configuration>

 

applicationContext-mybatis.xml

 

 

 

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

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 定義Mybatis的SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 定義數據源 -->
<property name="dataSource" ref="dataSource" />
<!-- 指定mybatis全局配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 掃描mappers目錄以及子目錄下的全部xml文件 -->
<property name="mapperLocations" value="classpath:mappers/**/*.xml" />
<!-- 別名掃描包 -->
<property name="typeAliasesPackage" value="cn.zto.mybatis.pojo"/>
</bean>
<!-- 定義Mapper -->
<!-- <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
指定Mapper接口的地址
<property name="mapperInterface" value="cn.zto.mybatis.mapper.UserMapper" />
sqlSessionFactory依賴
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean> -->
<!-- 定義Mapper接口掃描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.zto.mybatis.mapper" />
</bean>
</beans>



事務管理

Mybatis和spring整合後的事務管理是由Spring管理的,事務管理器依然使用jdbc的事務管理器,org.springframework.jdbc.datasource.DataSourceTransactionManager。 

相關文章
相關標籤/搜索