Spring學習總結(五)——Spring整合MyBatis(Maven+MySQL)一


MyBatis-Spring 會幫助你將 MyBatis 代碼無縫地整合到 Spring 中。 使用這個類庫中的類, Spring 將會加載必要的MyBatis工廠類和 session 類。 這個類庫也提供一個簡單的方式來注入MyBatis數據映射器和SqlSession到業務層的bean中。 而且它也會處理事務, 翻譯MyBatis的異常到Spring的 DataAccessException異常(數據訪問異常,譯者注)中。最終它並不會依賴於MyBatis,Spring或MyBatis-Spring來構建應用程序代碼。更多內容請查看官網幫助

一、 使用Maven創建一個Web項目

為了完成Spring4.x與MyBatis3.X的整合更加順利,先回顧在Maven環境下創建Web項目並使用MyBatis3.X,第一、二點內容多數是回顧過去的內容 。完成第一階段與第二階段的項目結構如下所示:

下載階段一與階段二示例

1.2、點擊“File”->“New”->"Other"->輸入“Maven”,新建一個“Maven Project”,如下圖所示:

1.2、請勾選“Create a simple project”,創建一個簡單的項目,不使用模板。也可以使用模板,選擇WebApp,不過這里就不應該勾選。如下圖所示:

1.3、填寫好包名、項目名,選擇打包類型為:war,如下圖所示:

1.4、項目創建好后可能會發現有錯誤,選擇項目,右鍵“屬性properties”->"層面Project Facets"->"Java"修改版本號為1.7,默認為1.5;點擊“Ok”保存后關閉。如下圖所示:

1.5、重復上一個步驟,反勾Dynamic Web Module,將項目暫時變成非Web項目。點擊“Ok”保存后關閉。

1.6、重復上一步驟,再進層面屬性,勾選“Dynamic Web Module”選擇Version為3.0。點擊左下角的超鏈接“Further Configuration available...“。

1.7、勾選“Generate web.xml deployment descriptor”生成web.xml部署描述文件。點擊“Ok”保存后關閉。

1.8、將生成的WebContent目錄下的兩個文件夾“META-INF”與“WEB-INF”復制到src/main/webapp目錄下。

1.9、刪除WebContent目錄。

1.10、刪除后會發現項目的pom.xml文件報錯,是因為找不到指定位置的web.xml文件引起的。再進入項目的屬性,選擇“Deployment Assembly”項目部署項,刪除“src/test/java”、“src/test/resources”與“WebContent”目錄,因為這三項不需要部署出去。

1.11、點擊“Add添加”后選擇“Folder文件夾”為項目的最終部署結果指定Web內容根文件夾。

1.12、選擇src\main\webapp目錄為目標目錄,點擊“Finish完成”保存並關閉。

1.13、如果此時項目還報錯,隨便修改pom.xml文件后保存后應該錯誤會消失。

 1.14、在src\main\webapp目錄下新建一個index.jsp文件,作為測試使用。

 

1.15、新建完成后發現有錯誤,是因為沒有JavaEE Server Runtime引起的,在項目上右鍵屬性選擇“Java Build Path”項,點擊“Add Library...”添加引用。

1.16、選擇Server Runtime項,點擊“Next下一步”,再選擇“Apache Tomcat v7.0”,這里可能要根據自己的運行環境選擇了,如果還沒Server,則應該先整合Tomcat。

1.17、在index.jsp文件中寫上測試內容。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World!</title>
</head>
<body>
Hello World!
<p>
<%=new java.util.Date().toLocaleString() %>
</p>
</body>
</html>

 1.18、在項目上右鍵選擇“Run as”-> “Run on Server”運行項目,運行結果如下。

二、使用MyBatis完成MySQL數據庫訪問

2.1、添加依賴

要完成使用MyBatis訪問MySQL數據庫,需要添加一些依賴包,包含MyBatis3,連接驅動,JUnit,Log4j2等。可以去共享資源庫中搜索,第一個網站地址是:http://mvnrepository.com/, 這里以搜索連接驅動為示例,搜索后的結果有5.xx版許多,也有6.xx版,但不建議使用6.xx版,因為MyBatis3不支持。

我們選擇5.0版中的5.1.38,將Maven的依賴信息復制到項目中的pom.xml的dependencies結點下

當然也可去另外一個網站:http://search.maven.org/,這里以log4j為例子搜索如下:

 

有一些依賴也可以直接去官網查找,如MyBatis3:

項目的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>
    <groupId>com.zhangguo</groupId>
    <artifactId>Spring061</artifactId>
    <version>0.0.1</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

引用結果:

如果在網速不穩定的情況下,下載包很有可能失敗,可以試試強制項目重新下載;可以使用下載工具將jar包下載后手復制到本地資源庫中。

2.2、准備數據

打開MySQL數據庫,創建一個表,這里以booktypes表為例。

sql腳本如下:

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50536
Source Host           : localhost:3306
Source Database       : db2

Target Server Type    : MYSQL
Target Server Version : 50536
File Encoding         : 65001

Date: 2016-07-04 10:49:56
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `booktypes`
-- ----------------------------
DROP TABLE IF EXISTS `booktypes`;
CREATE TABLE `booktypes` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '類型編號',
  `typeName` varchar(100) NOT NULL COMMENT '類型名稱',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=94 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of booktypes
-- ----------------------------
INSERT INTO `booktypes` VALUES ('1', '計算機軟件開發');
INSERT INTO `booktypes` VALUES ('2', '計算機網絡工程');
INSERT INTO `booktypes` VALUES ('3', '神話小說');
INSERT INTO `booktypes` VALUES ('4', '科幻小說');
INSERT INTO `booktypes` VALUES ('5', '外語');
INSERT INTO `booktypes` VALUES ('6', '測試類型');
INSERT INTO `booktypes` VALUES ('7', '91');
INSERT INTO `booktypes` VALUES ('8', '92');
INSERT INTO `booktypes` VALUES ('9', '93');
INSERT INTO `booktypes` VALUES ('91', '建築設計');
INSERT INTO `booktypes` VALUES ('92', '工業設計');
INSERT INTO `booktypes` VALUES ('93', '船舶制造');

2.3、創建java Bean

在包com.zhangguo.Spring61.entities下添加類BookType類型。

package com.zhangguo.Spring61.entities;

/**
 * 圖書類型
 *
 */
public class BookType {
    /**
     * 編號
     */
    private int id;
    /**
     * 類型名
     */
    private String typeName;

    public int getId() {
        return id;
    }

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

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }
    @Override
    public String toString() {
        return this.getId()+"\t"+this.getTypeName();
    }
}

2.4、創建實例與表的映射文件

這里用接口+XML的形式完成,BookType數據訪問接口如下:

package com.zhangguo.Spring61.mapping;

import java.util.List;

import com.zhangguo.Spring61.entities.BookType;

/**
 * 圖書類型數據訪問接口
 *
 */
public interface BookTypeDAO {
    /*
     * 獲得所有圖書類型
     */
    public List<BookType> getAllBookTypes();
}

BookTypeMapper.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="com.zhangguo.Spring61.mapping.BookTypeDAO">
    <!--id應該是接口中的方法,結果類型如沒有配置別名則應該使用全名稱 -->
    <select id="getAllBookTypes" resultType="BookType">
        select id,typeName from booktypes
    </select>
</mapper>

2.5、創建MyBatisCfg.xml文件 

MyBatisCfg.xml文件用於配置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>
    <!-- 指定數據庫連接信息的位置 -->
    <properties resource="db.properties"></properties>
    <!--類型別名,默認引入com.zhangguo.Spring61.entities下的所有類 -->
    <typeAliases>
        <package name="com.zhangguo.Spring61.entities"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--引入映射文件 -->
        <mapper resource="com/zhangguo/Spring61/mapping/BookTypeMapper.xml" />
    </mappers>
</configuration>

因為配置中依賴了db.properties文件,該文件用於指定數據庫的連接信息,內容如下:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db2
username=root
password=root

2.6、實現數據訪問功能

為了更加方便的復用MyBatis實現數據訪問不需要頻繁的創建SQLSessionFactory和SQLSession對象,封裝一個MyBatisUtil工具類如下:

package com.zhangguo.Spring61.dao;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public abstract class MyBatisUtil {
    
    //GC不理static
    private static SqlSessionFactory factory=null;
    public static SqlSessionFactory getSqlSessionFactory(){
        if(factory==null){
        // 獲得環境配置文件流
        InputStream config = MyBatisUtil.class.getClassLoader().getResourceAsStream("MyBatisCfg.xml");
        // 創建sql會話工廠
        factory = new SqlSessionFactoryBuilder().build(config);
        }
        return factory;
    }
    
    //獲得會話
    public static SqlSession getSession(){
        return getSqlSessionFactory().openSession(true);
    }
    
    /**
     * 獲得得sql會話
     * @param isAutoCommit 是否自動提交,如果為false則需要sqlSession.commit();rollback();
     * @return sql會話
     */
    public static SqlSession getSession(boolean isAutoCommit){
        return getSqlSessionFactory().openSession(isAutoCommit);
    }
    
}

創建類BookTypeDAOImpl實現接口BookTypeDAO,這里要通過MyBatis實現數據訪問功能,內容如下: 

package com.zhangguo.Spring61.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.zhangguo.Spring61.entities.BookType;
import com.zhangguo.Spring61.mapping.BookTypeDAO;

/**
 * 實現圖書類型數據訪問
 *
 */
public class BookTypeDAOImpl implements BookTypeDAO {

    @Override
    public List<BookType> getAllBookTypes() {
        //獲得會話對象
        SqlSession session=MyBatisUtil.getSession();
        try {
            //通過MyBatis實現接口BookTypeDAO,返回實例
            BookTypeDAO bookTypeDAO=session.getMapper(BookTypeDAO.class);
            return bookTypeDAO.getAllBookTypes();
        } finally {
            session.close();
        }
    }

}

2.7、測試運行

新建一個JUnit Test Case測試用例,如下所示:

 測試用例TestBookTypeDAOImpl.java文件如下:

package com.zhangguo.Spring61.test;

import static org.junit.Assert.*;

import java.util.List;

import org.junit.BeforeClass;
import org.junit.Test;

import com.zhangguo.Spring61.dao.BookTypeDAOImpl;
import com.zhangguo.Spring61.entities.BookType;
import com.zhangguo.Spring61.mapping.BookTypeDAO;

public class TestBookTypeDAOImpl {

    static BookTypeDAO bookTypeDao;
    @BeforeClass
    public static void beforeClass()
    {
        bookTypeDao=new BookTypeDAOImpl();
    }
    
    @Test
    public void testGetAllBookTypes() {
        List<BookType> booktypes=bookTypeDao.getAllBookTypes();
        for (BookType bookType : booktypes) {
            System.out.println(bookType);
        }
        assertNotNull(booktypes);
    }

}

測試結果:

2.8、整合log4j2

上面的測試雖然通過,但是有一個錯誤提示“ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.”,大意是:日志記錄器沒有找到log4j2的配置文件。在源碼的根目錄下創建一個log4j2.xml配置文件,文件內容如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="off" monitorInterval="1800">    
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>        
    </Appenders>

    <Loggers>            
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

再運行就會發現log4j2已經在運行了,從控制台可以看到MyBatis的運行狀態信息:

程序向數據庫發送的SQL請求,及數據庫向程序響應的結果就清楚了。

下載階段一與階段二示例

三、使用Spring4.X整合MyBatis3.X初級版

在MyBatis的github官網(https://github.com/mybatis/spring)中有一個叫MyBatis Spring Adapter(MyBatis-Spring)的庫,暫且翻譯成:MyBatis Spring適配器,它的作用是:原話:“MyBatis-Spring adapter is an easy-to-use Spring3 bridge for MyBatis sql mapping framework.”,就是了為更容易的將MyBatis與Spring整合,充分發揮二兩結合的優勢,它相當於一個橋。

什么是:MyBatis-Spring?
MyBatis-Spring會幫助你將MyBatis代碼無縫地整合到Spring中。使用這個類庫中的類,Spring將會加載必要的MyBatis工廠類和session類。這個類庫也提供一個簡單的方式來注入MyBatis數據映射器和SqlSession到業務層的bean中。而且它也會處理事務,翻譯MyBatis的異常到Spring的DataAccessException異常(數據訪問異常,譯者注)中。最終,它並不會依賴於MyBatis,Spring或MyBatis-Spring來構建應用程序代碼。

3.1、修改pom.xml添加依賴

為了將Spring與MyBatis整合完成,需要依賴MyBatis,因為在上面的示例中已依賴完成,這里就不再需要,主要需依賴的是Spring核心,AOP,JDBC,MyBatis-Spring等jar包。具體的依賴結果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>
    <groupId>com.zhangguo</groupId>
    <artifactId>Spring061</artifactId>
    <version>0.0.1</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.3.0.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--mysql數據庫驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!--log4j日志包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.6.1</version>
        </dependency>
        <!-- mybatis ORM框架 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!-- JUnit單元測試工具 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <!--mybatis-spring適配器 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--Spring框架核心庫 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- aspectJ AOP 織入器 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!--Spring java數據庫訪問包,在本例中主要用於提供數據源 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</project>

 3.2、創建Spring上下文初始化配置文件

該文件取名為ApplicationContext.xml主要原因是“約束優於配置”的理由,使用Web監聽器加載Spring時會默認找該名稱的文件。在文件中我們可像以前學習Spring一樣配置IOC與AOP,只不過這里整合了一些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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!--1定義一個jdbc數據源,創建一個驅動管理數據源的bean -->
    <bean id="jdbcDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/db2" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <!--2創建一個sql會話工廠bean,指定數據源-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="jdbcDataSource" /><!-- 指定數據源 -->
        <property name="configLocation" value="classpath:MyBatisCfg.xml"></property> <!-- 指定配置文件 -->
    </bean>

    <!--3創建一個booTypeDAO-->
    <bean id="bookTypeDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <!--指定映射文件 -->
        <property name="mapperInterface" value="com.zhangguo.Spring61.mapping.BookTypeDAO"></property>
        <!-- 指定sql會話工廠-->
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
    <!--下面的配置暫時未使用 -->
    <context:component-scan base-package="com.zhangguo">
    </context:component-scan>
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

從上面的代碼可以看到分別創建了一個驅動管理數據源的對象,會話工廠與實現數據訪問的對象通過Spring IOC完成,而不再是硬編碼。第2段配置與下面的代碼功能基本類似:

    private static SqlSessionFactory factory=null;
    public static SqlSessionFactory getSqlSessionFactory(){
        if(factory==null){
        // 獲得環境配置文件流
        InputStream config = MyBatisUtil.class.getClassLoader().getResourceAsStream("MyBatisCfg.xml");
        // 創建sql會話工廠
        factory = new SqlSessionFactoryBuilder().build(config);
        }
        return factory;
    }

第3段配置與下面的java代碼基本類似:

        SqlSession session = MyBatisUtil.getSession();
        try {
            BookTypeDAO bookTypeDAO = session.getMapper(BookTypeDAO.class);
            return bookTypeDAO.getAllBookTypes();
        } finally {
            session.close();
        }

 3.3、測試運行

package com.zhangguo.Spring61.test;

import static org.junit.Assert.assertNotNull;

import java.util.List;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zhangguo.Spring61.entities.BookType;
import com.zhangguo.Spring61.mapping.BookTypeDAO;

public class TestMyBatisSpring01 {
    @Test
    public void test01() {
        //初始化容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
        //獲得bean
        BookTypeDAO bookTypeDao=ctx.getBean("bookTypeDao",BookTypeDAO.class);
        //訪問數據庫
        List<BookType> booktypes=bookTypeDao.getAllBookTypes();
        for (BookType bookType : booktypes) {
            System.out.println(bookType);
        }
        assertNotNull(booktypes);
    }
}

 運行結果:

小結:此處的整合還是相對基礎,更完善的整合內容將在后面的章節實現。另外在MyBatisCfg.xml文件中可以刪除運行環境中數據源配置部分的內容,如下圖所示。我們當前的示例使用的是Spring提供的數據源,其實也可以使用一第三方的數據源管理,如C3P0,Druid(德魯伊,阿里巴巴開發)等。

 下載第三階段示例

 四、Spring集成MyBatis升級版

 4.1、去掉MyBatisCfg.xml配置文件

在沒有Spring的環境下我們單純使用MyBatis ORM框架時,我們是通過MyBatisCfg.xml完成sqlSessionFactory的構建工作,如果使用Spring則這部分配置的內容可以完全由Spring容器替代,具體實現如下:

    <!--創建一個sql會話工廠bean,指定數據源 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 1指定數據源 -->
        <property name="dataSource" ref="jdbcDataSource" />
        <!-- 2類型別名包,默認引入com.zhangguo.Spring61.entities下的所有類 -->
        <property name="typeAliasesPackage" value="com.zhangguo.Spring61.entities"></property>
        <!-- 3指定sql映射xml文件的路徑 -->
        <property name="mapperLocations"
            value="classpath:com/zhangguo/Spring61/mapping/*Mapper.xml"></property>
    </bean>

mapperLocations:它表示我們的Mapper文件存放的位置,當我們的Mapper文件跟對應的Mapper接口處於同一位置的時候可以不用指定該屬性的值。

configLocation:用於指定Mybatis的配置文件位置。如果指定了該屬性,那么會以該配置文件的內容作為配置信息構建對應的SqlSessionFactoryBuilder,但是后續屬性指定的內容會覆蓋該配置文件里面指定的對應內容。

typeAliasesPackage:它一般對應我們的實體類所在的包,這個時候會自動取對應包中不包括包名的簡單類名作為包括包名的別名。多個package之間可以用逗號或者分號等來進行分隔。

typeAliases:數組類型,用來指定別名的。指定了這個屬性后,Mybatis會把這個類型的短名稱作為這個類型的別名,前提是該類上沒有標注@Alias注解,否則將使用該注解對應的值作為此種類型的別名。

<property name="typeAliases">
    <array>
        <value>com.tiantian.mybatis.model.Blog</value>
        <value>com.tiantian.mybatis.model.Comment</value>
    </array>
</property>

我們修改了applicationContext.xml中的配置,通過容器完成了一個sqlSessionFactory Bean的創建, 1指定了數據源,2指定類型別名包這樣在sql映射文件中使用類型時可以省去全名稱,3指定了所有要加載的sql映射xml文件,如果有多個目錄,則可以使用如下的形式:

       <property name="mapperLocations">
            <list>
                <value>classpath:com/...目錄.../*_mapper.xml</value>
                <value>classpath:com/...目錄.../*_resultmap.xml</value>
            </list>
        </property>

如果需要設置更多的屬性則可以參考類型org.mybatis.spring.SqlSessionFactoryBean,如果不使用Spring,也不使用MyBatis配置文件我們照樣可以獲得一個sqlSessionFactory對象完成對MyBatis ORM框架的使用,因為可以直接實例化一個SqlSessionFactoryBean對象,只是此時該工作被Spring容器替代,按這個思路可以在SqlSessionFactoryBean類中找到更多的屬性設置在applicationContext.xml配置中,部分源代碼如下所示:

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {

  private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);

  private Resource configLocation;

  private Configuration configuration;

  private Resource[] mapperLocations;

  private DataSource dataSource;

  private TransactionFactory transactionFactory;

  private Properties configurationProperties;

  private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

  private SqlSessionFactory sqlSessionFactory;

  //EnvironmentAware requires spring 3.1
  private String environment = SqlSessionFactoryBean.class.getSimpleName();

  private boolean failFast;

  private Interceptor[] plugins;

  private TypeHandler<?>[] typeHandlers;

  private String typeHandlersPackage;

  private Class<?>[] typeAliases;

  private String typeAliasesPackage;

  private Class<?> typeAliasesSuperType;

  //issue #19. No default provider.
  private DatabaseIdProvider databaseIdProvider;

  private Class<? extends VFS> vfs;

  private Cache cache;

  private ObjectFactory objectFactory;

  private ObjectWrapperFactory objectWrapperFactory;
}

如果習慣兩者結合使用,當然還是可以指定MyBatis配置文件的,增加屬性:<property name="configLocation" value="classpath:MyBatisCfg.xml"></property>

4.2、映射接口類自動掃描配置

在示例3的applicationContext.xml配置文件中有一段實現BookTypeDAO接口實例的創建工廠,配置如下:

    <!-- 創建一個booTypeDAO -->
    <bean id="bookTypeDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <!--指定映射文件 -->
        <property name="mapperInterface" value="com.zhangguo.Spring61.mapping.BookTypeDAO"></property>
        <!-- 指定sql會話工廠 -->
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>

 如果有多個表,則需要配置多段信息,麻煩。我們可以通過自動掃描一次完成,配置如下:

    <!--自動掃描映射接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定sql會話工廠,在上面配置過的 -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!-- 指定基礎包,即自動掃描com.zhangguo.Spring61.mapping這個包以及它的子包下的所有映射接口類 -->
        <property name="basePackage" value="com.zhangguo.Spring61.mapping"></property>
    </bean>

 需要注意的是這里的sql會話工廠的指定可以使用sqlSessionFactoryBeanName屬性指定,也可以使用sqlSessionFactory屬性指定,但建議大家使用sqlSessionFactoryBeanName,否則會因為加載的先后順序問題引起讀不到properties文件的內容。其它屬性的設置可以查看源碼后再定義。

這樣MapperScannerConfigurer就會掃描指定basePackage下面的所有接口,並把它們注冊為一個個MapperFactoryBean對象。basePackage下面的並不全是我們定義的Mapper接口,為此MapperScannerConfigurer還為我們提供了另外兩個可以縮小搜索和注冊范圍的屬性。一個是annotationClass,另一個是markerInterface。
annotationClass:當指定了annotationClass的時候,MapperScannerConfigurer將只注冊使用了annotationClass注解標記的接口。
markerInterface:markerInterface是用於指定一個接口的,當指定了markerInterface之后,MapperScannerConfigurer將只注冊繼承自markerInterface的接口。

sqlSessionFactory: 已廢棄 。當使用多個數據源時就需要通過sqlSessionFactory來指定注冊MapperFactoryBean的時候需要使用的SqlSessionFactory,因為在沒有指定sqlSessionFactory的時候,會以Autowired的方式自動注入一個。換言之當我們只使用一個數據源的時候,即只定義了一個SqlSessionFactory的時候我們就可以不給MapperScannerConfigurer指定SqlSessionFactory。
sqlSessionFactoryBeanName:它的功能跟sqlSessionFactory是一樣的,只是它指定的是定義好的SqlSessionFactory對應的bean名稱。
sqlSessionTemplate: 已廢棄 。它的功能也是相當於sqlSessionFactory的,MapperFactoryBean最終還是使用的SqlSession的getMapper方法取的對應的Mapper對象。當定義有多個SqlSessionTemplate的時候才需要指定它。對於一個MapperFactoryBean來說SqlSessionFactory和SqlSessionTemplate只需要其中一個就可以了,當兩者都指定了的時候,SqlSessionFactory會被忽略。
sqlSessionTemplateBeanName:指定需要使用的sqlSessionTemplate對應的bean名稱。

4.3、引入屬性配置文件db.properties

從示例3的配置代碼中可以發現數據庫連接字符信息同時出現在兩個位置,分別是applicationContext.xml與db.properties文件中,如下所示:

    <!--定義一個jdbc數據源,創建一個驅動管理數據源的bean -->
    <bean id="jdbcDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/db2" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db2
username=root
password=root

根據我們寫代碼的原則“Write once only once”,連接字符信息應該只存在一個位置,我們可以采用下面的方法整合:

修改后的db.properties文件內容如下:

#jdbc
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=UTF-8
jdbc.uid=root
jdbc.pwd=root

#other ..
other.msg=hello

修改后的 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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!--屬性占位文件引入,可以通過${屬性名}獲得屬性文件中的內容-->
    <context:property-placeholder location="classpath:db.properties"/>
    
    <!--定義一個jdbc數據源,創建一個驅動管理數據源的bean -->
    <bean id="jdbcDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.uid}" />
        <property name="password" value="${jdbc.pwd}" />
    </bean>

    <!--創建一個sql會話工廠bean,指定數據源 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 指定數據源 -->
        <property name="dataSource" ref="jdbcDataSource" />
        <!--類型別名包,默認引入com.zhangguo.Spring61.entities下的所有類 -->
        <property name="typeAliasesPackage" value="com.zhangguo.Spring61.entities"></property>
        <!--指定sql映射xml文件的路徑 -->
        <property name="mapperLocations"
            value="classpath:com/zhangguo/Spring61/mapping/*Mapper.xml"></property>
    </bean>
    
    <!--自動掃描映射接口-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定sql會話工廠,在上面配置過的 -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <!-- 指定基礎包,即自動掃描com.zhangguo.Spring61.mapping這個包以及它的子包下的所有映射接口類 -->
        <property name="basePackage" value="com.zhangguo.Spring61.mapping"></property>
    </bean>
    
    <!--下面的配置暫時未使用 -->
    <context:component-scan base-package="com.zhangguo.Spring61">
    </context:component-scan>
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

測試運行代碼如下:

package com.zhangguo.Spring61.test;

import static org.junit.Assert.assertNotNull;

import java.util.List;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zhangguo.Spring61.entities.BookType;
import com.zhangguo.Spring61.mapping.BookTypeDAO;

public class TestMyBatisSpring01 {
    @Test
    public void test01() {
        //初始化容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
        //獲得bean
        BookTypeDAO bookTypeDao=ctx.getBean(BookTypeDAO.class);
        //訪問數據庫
        List<BookType> booktypes=bookTypeDao.getAllBookTypes();
        for (BookType bookType : booktypes) {
            System.out.println(bookType);
        }
        assertNotNull(booktypes);
    }
}

測試結果同第3階段,成功!

4.4、數據源與連接池

 通過連接池可以增加數據訪問的性能,因為訪問數據庫時建立連接與釋放連接是耗時操作,JDBC默認不帶連接池技術,但MyBatis是內置連接池功能的,還有一些第三方知名的連接池技術如:DBCP、C3P0、Druid(德魯伊)。

4.4.1、DBCP

DBCP 是 Apache 軟件基金組織下的開源連接池實現,要使用DBCP數據源,需要應用程序應在系統中增加如下兩個 jar 文件:Commons-dbcp.jar:連接池的實現、Commons-pool.jar:連接池實現的依賴庫,常用屬性如下:

#連接設置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy
username=root
password=XDP

#<!-- 初始化連接 -->
initialSize=10
#最大連接數量
maxActive=50
#<!-- 最大空閑連接 -->
maxIdle=20
#<!-- 最小空閑連接 -->
minIdle=5
#<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等於60秒 -->
maxWait=60000
#JDBC驅動建立連接時附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;] 
#注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這里不需要包含他們。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由連接池所創建的連接的自動提交(auto-commit)狀態。
defaultAutoCommit=true
#driver default 指定由連接池所創建的連接的只讀(read-only)狀態。
#如果沒有設置該值,則“setReadOnly”方法將不被調用。(某些驅動並不支持只讀模式,如:Informix)
defaultReadOnly=
#driver default 指定由連接池所創建的連接的事務級別(TransactionIsolation)。
#可用值為下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

 在與Spring整合時設置:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/hlp?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull"></property>
        <property name="username" value="root"></property>
        <property name="password" value="1234"></property>
        <property name="maxActive" value="100"></property>
        <property name="maxIdle" value="30"></property>
        <property name="maxWait" value="500"></property>
        <property name="defaultAutoCommit" value="true"></property>
    </bean>

 使用上面的代碼替換原數據源的創建。

4.4.2、C3P0

C3P0是一個開源的JDBC連接池,它實現了數據源和JNDI綁定,支持JDBC3規范和JDBC2的標准擴展。目前使用它的開源項目有Hibernate,Spring等。C3P0數據源在項目開發中使用得比較多。dbcp沒有自動回收空閑連接的功能,而c3p0有自動回收空閑連接功能。

在pom.xml中添加依賴:

        <!--c3p0 連接池 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>

 在與Spring整合時修改applicationContext.xml,設置如下:

    <!--定義一個jdbc數據源,創建一個驅動管理數據源的bean -->
    <bean id="jdbcDataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${jdbc.driver}" />
        <property name="jdbcUrl" value="${jdbc.url}" />
        <property name="user" value="${jdbc.uid}" />
        <property name="password" value="${jdbc.pwd}" />
        <property name="acquireIncrement" value="5"></property>
        <property name="initialPoolSize" value="10"></property>
        <property name="minPoolSize" value="5"></property>
        <property name="maxPoolSize" value="20"></property>
    </bean>

在測試的代碼中設置斷點,查看連接數,顯示結果如下:

關於c3p0屬性的細節與查看連接數據的方法請查看我的另一篇文章:Hibernate整合C3P0實現連接池 常用屬性如下:

<!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3 -->
<property name="acquireIncrement">3</property>
<!--定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default: 30 -->
<property name="acquireRetryAttempts">30</property>
<!--兩次連接中間隔時間,單位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">1000</property>
<!--連接關閉時默認將所有未提交的操作回滾。Default: false -->
<property name="autoCommitOnClose">false</property>
<!--c3p0將建一張名為Test的空表,並使用其自帶的查詢語句進行測試。如果定義了這個參數那么
屬性preferredTestQuery將被忽略。你不能在這張Test表上進行任何操作,它將只供c3p0測試
使用。Default: null-->
<property name="automaticTestTable">Test</property>
<!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數據源仍有效
保留,並在下次調用getConnection()的時候繼續嘗試獲取連接。如果設為true,那么在嘗試
獲取連接失敗后該數據源將申明已斷開並永久關閉。Default: false-->
<property name="breakAfterAcquireFailure">false</property>
<!--當連接池用完時客戶端調用getConnection()后等待獲取新連接的時間,超時后將拋出
SQLException,如設為0則無限期等待。單位毫秒。Default: 0 -->
<property name="checkoutTimeout">100</property>
<!--通過實現ConnectionTester或QueryConnectionTester的類來測試連接。類名需制定全路徑。
Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester-->
<property name="connectionTesterClassName"></property>
<!--指定c3p0 libraries的路徑,如果(通常都是這樣)在本地即可獲得那么無需設置,默認null即可
Default: null-->
<property name="factoryClassLocation">null</property>
<!--Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs.
(文檔原文)作者強烈建議不使用的一個屬性-->
<property name="forceIgnoreUnresolvedTransactions">false</property>
<!--每60秒檢查所有連接池中的空閑連接。Default: 0 -->
<property name="idleConnectionTestPeriod">60</property>
<!--初始化時獲取三個連接,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->
<property name="initialPoolSize">3</property>
<!--最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。Default: 0 -->
<property name="maxIdleTime">60</property>
<!--連接池中保留的最大連接數。Default: 15 -->
<property name="maxPoolSize">15</property>
<!--JDBC的標准參數,用以控制數據源內加載的PreparedStatements數量。但由於預緩存的statements
屬於單個connection而不是整個連接池。所以設置這個參數需要考慮到多方面的因素。
如果maxStatements與maxStatementsPerConnection均為0,則緩存被關閉。Default: 0-->
<property name="maxStatements">100</property>
<!--maxStatementsPerConnection定義了連接池內單個連接所擁有的最大緩存statements數。Default: 0 -->
<property name="maxStatementsPerConnection"></property>
<!--c3p0是異步操作的,緩慢的JDBC操作通過幫助進程完成。擴展這些操作可以有效的提升性能
通過多線程實現多個操作同時被執行。Default: 3-->
<property name="numHelperThreads">3</property>
<!--當用戶調用getConnection()時使root用戶成為去獲取連接的用戶。主要用於連接池連接非c3p0
的數據源時。Default: null-->
<property name="overrideDefaultUser">root</property>
<!--與overrideDefaultUser參數對應使用的一個參數。Default: null-->
<property name="overrideDefaultPassword">password</property>
<!--密碼。Default: null-->
<property name="password"></property>
<!--定義所有連接測試都執行的測試語句。在使用連接測試的情況下這個一顯著提高測試速度。注意:
測試的表必須在初始數據源的時候就存在。Default: null-->
<property name="preferredTestQuery">select id from test where id=1</property>
<!--用戶修改系統配置參數執行前最多等待300秒。Default: 300 -->
<property name="propertyCycle">300</property>
<!--因性能消耗大請只在需要的時候使用它。如果設為true那么在每個connection提交的
時候都將校驗其有效性。建議使用idleConnectionTestPeriod或automaticTestTable
等方法來提升連接測試的性能。Default: false -->
<property name="testConnectionOnCheckout">false</property>
<!--如果設為true那么在取得連接的同時將校驗連接的有效性。Default: false -->
<property name="testConnectionOnCheckin">true</property>
<!--用戶名。Default: null-->
<property name="user">root</property>
在Hibernate(spring管理)中的配置:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass"><value>oracle.jdbc.driver.OracleDriver</value></property>
<property name="jdbcUrl"><value>jdbc:oracle:thin:@localhost:1521:Test</value></property>
<property name="user"><value>Kay</value></property>
<property name="password"><value>root</value></property>
<!--連接池中保留的最小連接數。-->
<property name="minPoolSize" value="10" />
<!--連接池中保留的最大連接數。Default: 15 -->
<property name="maxPoolSize" value="100" />
<!--最大空閑時間,1800秒內未使用則連接被丟棄。若為0則永不丟棄。Default: 0 -->
<property name="maxIdleTime" value="1800" />
<!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3 -->
<property name="acquireIncrement" value="3" />
<property name="maxStatements" value="1000" />
<property name="initialPoolSize" value="10" />
<!--每60秒檢查所有連接池中的空閑連接。Default: 0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!--定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default: 30 -->
<property name="acquireRetryAttempts" value="30" />
<property name="breakAfterAcquireFailure" value="true" />
<property name="testConnectionOnCheckout" value="false" />
</bean>
編輯本段相關信息連接池配置(以Hibernate為例)
###########################
### C3P0 Connection Pool###
###########################
#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false
在hibernate.cfg.xml文件里面加入如下的配置:
<!-- 最大連接數 -->
<property name="hibernate.c3p0.max_size">20</property>
<!-- 最小連接數 -->
<property name="hibernate.c3p0.min_size">5</property>
<!-- 獲得連接的超時時間,如果超過這個時間,會拋出異常,單位毫秒 -->
<property name="hibernate.c3p0.timeout">120</property>
<!-- 最大的PreparedStatement的數量 -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- 每隔120秒檢查連接池里的空閑連接 ,單位是秒-->
<property name="hibernate.c3p0.idle_test_period">120</property>
<!-- 當連接池里面的連接用完的時候,C3P0一下獲取的新的連接數 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!-- 每次都驗證連接是否可用 -->
<property name="hibernate.c3p0.validate">true</property>
c3p0常用屬性 +展開

4.4.3、Druid(德魯伊)

Druid首先是一個數據庫連接池,但它不僅僅是一個數據庫連接池,它還包含一個ProxyDriver,一系列內置的JDBC組件庫,一個SQL Parser。阿里巴巴是一個重度使用關系數據庫的公司,我們在生產環境中大量的使用Druid,通過長期在極高負載的生產環境中實際使用、修改和完善,讓Druid逐步發展成最好的數據庫連接池。Druid在監控、可擴展性、穩定性和性能方面都有明顯的優勢。

在與Spring整合時設置:

<!-- 配置數據源,使用的是alibaba的Druid(德魯伊)數據源 -->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc_url}" />
        <property name="username" value="${jdbc_username}" />
        <property name="password" value="${jdbc_password}" />
        <!-- 初始化連接大小 -->
        <property name="initialSize" value="0" />
        <!-- 連接池最大使用連接數量 -->
        <property name="maxActive" value="20" />
        <!-- 連接池最大空閑 -->
        <property name="maxIdle" value="20" />
        <!-- 連接池最小空閑 -->
        <property name="minIdle" value="0" />
        <!-- 獲取連接最大等待時間 -->
        <property name="maxWait" value="60000" />
        <!-- 
        <property name="poolPreparedStatements" value="true" /> 
        <property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> 
        -->
        <property name="validationQuery" value="${validationQuery}" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />
        <property name="testWhileIdle" value="true" />
        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000" />
        <!-- 打開removeAbandoned功能 -->
        <property name="removeAbandoned" value="true" />
        <!-- 1800秒,也就是30分鍾 -->
        <property name="removeAbandonedTimeout" value="1800" />
        <!-- 關閉abanded連接時輸出錯誤日志 -->
        <property name="logAbandoned" value="true" />
        <!-- 監控數據庫 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat" />
    </bean>

 使用上面的代碼替換原數據源的創建。

 maven依賴方式:

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.0.20</version>
</dependency>

 github:https://github.com/alibaba/druid,阿里的其它開源框架:https://github.com/alibaba

4.5、使用SqlSession

Mybatis-Spring為我們提供了一個實現了SqlSession接口的SqlSessionTemplate類,它是線程安全的,可以被多個Dao同時使用。同時它還跟Spring的事務進行了關聯,確保當前被使用的SqlSession是一個已經和Spring的事務進行綁定了的。而且它還可以自己管理Session的提交和關閉。當使用了Spring的事務管理機制后,SqlSession還可以跟着Spring的事務一起提交和回滾。修改applicationContext.xml文件,增加一個bean。

SqlSessionTemplate 是 MyBatis-Spring 的核心。 這個類負責管理 MyBatis 的 SqlSession, 調用 MyBatis 的 SQL 方法, 翻譯異常。 SqlSessionTemplate 是線程安全的, 可以被多個 DAO 所共享使用。
當調用 SQL 方法時, 包含從映射器 getMapper()方法返回的方法, SqlSessionTemplate 將會保證使用的 SqlSession 是和當前 Spring 的事務相關的。此外,它管理 session 的生命 周期,包含必要的關閉,提交或回滾操作。
SqlSessionTemplate 實現了 SqlSession 接口,這就是說,在代碼中無需對 MyBatis 的 SqlSession 進行替換。 SqlSessionTemplate 通常是被用來替代默認的 MyBatis 實現的 DefaultSqlSession , 因為模板可以參與到 Spring 的事務中並且被多個注入的映射器類所使 用時也是線程安全的。相同應用程序中兩個類之間的轉換可能會引起數據一致性的問題。
SqlSessionTemplate 對象可以使用 SqlSessionFactory 作為構造方法的參數來創建。

    <!-- 創建一個sqlSession對象 -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>
    
    <!--創建一個BTDImpl對象 -->
    <bean id="bTDImpl" class="com.zhangguo.Spring61.dao.BTDImpl">
        <property name="sqlSession" ref="sqlSession"></property>
    </bean>

新增一個BTDImpl類,實現接口BookTypeDAO,具體如下:

package com.zhangguo.Spring61.dao;

import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.zhangguo.Spring61.entities.BookType;
import com.zhangguo.Spring61.mapping.BookTypeDAO;

public class BTDImpl implements BookTypeDAO {
    private SqlSession sqlSession;

    public void setSqlSession(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<BookType> getAllBookTypes() {
        return sqlSession.selectList("com.zhangguo.Spring61.mapping.BookTypeDAO.getAllBookTypes");
    }

}

使用Spring的依賴注入在DAO中直接使用SqlSessionTemplate來訪問數據庫了。

測試代碼:

package com.zhangguo.Spring61.test;

import static org.junit.Assert.assertNotNull;
import java.util.List;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zhangguo.Spring61.dao.BTDImpl;
import com.zhangguo.Spring61.entities.BookType;

public class TestMyBatisSpring02 {
    @Test
    public void test01() {
        //初始化容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
        //獲得bean
        BTDImpl bTDImpl=ctx.getBean("bTDImpl",BTDImpl.class);
        //訪問數據庫
        List<BookType> booktypes=bTDImpl.getAllBookTypes();
        for (BookType bookType : booktypes) {
            System.out.println(bookType);
        }
        assertNotNull(booktypes);
    }
}

運行結果:

 

也可以通過自動裝配實現,使配置更加簡單,在配置文件中可以刪除“創建一個BTDImpl對象”這一段,在類BTDImpl中增加注解,代碼如下:

package com.zhangguo.Spring61.dao;

import java.util.List;

import javax.annotation.Resource;

import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;

import com.zhangguo.Spring61.entities.BookType;
import com.zhangguo.Spring61.mapping.BookTypeDAO;

@Repository public class BTDImpl implements BookTypeDAO {
    @Resource private SqlSession sqlSession;

    public void setSqlSession(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<BookType> getAllBookTypes() {
        return sqlSession.selectList("com.zhangguo.Spring61.mapping.BookTypeDAO.getAllBookTypes");
    }

}

 測試方法獲得bean要修改成:BTDImpl bTDImpl=ctx.getBean(BTDImpl.class);,運行結果同上。

 實在太亂了,應大家的要求,打算在另外一篇文章中再繼續寫。

五、示例下載

點擊下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM