前言
MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以對配置和原生Map使用簡單的 XML 或注解,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。
—— 摘自 MyBatis 中文官網,http://www.mybatis.org/mybatis-3/zh/
Spring 與 MyBatis 集成
MyBatis 與 Spring 的集成思路,總共有以下幾個步驟:
- 引入 MyBatis 與 Spring 框架相關的包,數據庫驅動的包,可引入數據庫連接池、日志、測試相關包
- 配置XML,包括數據源 DataSource (用于指定數據庫連接地址、賬號、密碼等數據庫配置)和 SqlSessionFactory (用于指定 MyBatis 自動載入的 *Mapper.xml)
- 編寫 Entity 類,用來存儲數據庫查詢返回數據,一般而言,成員變量對應數據庫表字段名,僅提供 getter/setter 方法
- 編寫 Mapper 接口 與 Mapper.xml ,Mapper 接口 指定操作名,并規定好傳入參數,Mapper.xml 為數據庫操作的 SQL ,id 需要與 Mapper 接口 一致
- 創建數據庫,編寫服務,測試
一、Maven 引入 jar 包
在 Maven 項目中的 pom.xml 文件增加以下依賴。項目一般還需要增加 log 日志模塊、junit 測試模塊等,在此 pom.xml 不再贅述。
<dependencies>
<!-- Maven Lib -->
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spri
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- 連接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- mysql driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
</dependencies>
二、創建數據庫環境
因為 MyBatis 框架是解決持久化或者說數據庫的問題,因此我們需要配置一下數據庫環境。
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` INT(12) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`age` INT(4) DEFAULT 0,
`gender` INT(2),
PRIMARY KEY(`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
三、配置 sqlSessionFactory 與 DataSource
要使用 MyBatis ,至少需要一個 SqlSessionFactoryBean 是用于創建 SqlSessionFactory 的。要配置這個 Factory bean ,放置下面的代碼在 Spring 的 XML 配置文件中。我在配置時,將數據庫相關的配置都創建了一個獨立的 XML 配置文件,然后在 Spring 主配置文件中通過 import 引用。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/sc ma/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSc ma-instance"
xsi:sc maLocation="http://www.springframework.org/sc ma/beans http://www.springframework.org/sc ma/beans/spring-beans.xsd">
<!-- mysql data source -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" lazy-init="false">
<property name="driverClass" value="${jdbc.driverclass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="testConnectionOnC ckout" value="false"/>
<property name="initialPoolSize" value="2"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="50"/>
<property name="acquireIncrement" value="1"/>
<property name="acquireRetryAttempts" value="1"/>
<property name="maxIdleTime" value="6000"/>
<property name="maxStatements" value="0"/>
</bean>
<!-- SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- Mapper文件存放的位置,當Mapper文件跟對應的Mapper接口處于同一位置的時候可以不用指定該屬性的值 -->
<property name="mapperLocations" value="classpath*:sqlmap/*.xml"/>
</bean>
<!-- DAO Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="annotationClass" value="org.springframework.stereotype.Repository" />
<!-- 掃描器開始掃描的基礎包名,支持嵌套掃描 -->
<property name="basePackage" value="com.test.dao.mapper" />
</bean>
</beans>
以上是 my-db.xml 配置文件,主要分為三部分:
- datasource ,數據源,與數據庫連接相關,配置數據庫的地址、賬戶、密碼,一些配置等等,從 jdbc.properties 文件中載入。關于 Spring 如何載入 properties 文件如何實現,不在這篇文章贅述了。
- sqlSessionFactory ,數據庫會話工廠。從
*Mapper.xml
中文件自動載入<mapper>
- Mapper 類 ,在此配置中采用 Scanner 方式,自動從 mapper 包內載入 mapper 類。
四、調用 MyBatis 框架
創建 Entity,映射 Database 表(或有)
在 entity 包中創建實體,對應 t_user 表 的返回。成員變量一般與數據庫表字段名一一對應,成員方法僅提供 getter/setter 方法。
實體類不是必須的,MyBatis 提供將數據庫返回簡單的映射到 Map 或 HashMap 結構中,而非 POJO 中。
/**
* t_user 表實體
*/
public class User implements Serializable {
private int id;
private String name;
private int age;
private int gender;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getGender() { return gender; }
public void setGender(int gender) { this.gender = gender; }
}
創建 DAO/Mapper
在 dao.mapper
包內創建 UserMapper 接口 ,并添加 @Repository
注解
@Repository
public interface UserMapper {
public List<User> findUserById(int id);
public Integer insertUser(User user);
}
對應具體數據庫的方法,例如插入用戶、通過 id 查找用戶。每次需要定義一個數據庫操作,就在 Mapper 類中定義一個接口。
注意,因為在三、配置 sqlSessionFactory 與 DataSource ,定義了自動載入 Mapper 類 。因此,需要加入了
@Repository
的注解,用于標注數據訪問組件,即DAO 組件。否則不需要 @Repository 注解,但需要在*Mapper.xml
中增加<mapper>
配置。
配置 Mapper.xml
在 Mapper.xml
中編寫具體的數據庫操作的 SQL。
其中,tag 有 insert, select, update 等
id 與 Mapper 接口方法名一一對應;
parameterType 為傳入參數,可以是 POJO,也可以是 int、String 這種基本類型,SQL 中的參數用 #{id} 的形式表示;
resultType 或者 resultMap ,都是存儲返回的結果集,其中 resultMap 比較強大,靈活;resultType 可以簡單指定為 map 或者 POJO。
<?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.test.dao.mapper.UserMapper">
<!--配置一個resultMap 指定返回的類型 -->
<resultMap id="userInfo" type="com.test.entity.User">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
</resultMap>
<select id="queryUserInfos" resultMap="userInfo" parameterType="java.lang.Integer">
SELECT * FROM t_user W RE age = #{age} ORDER BY id DESC;
</select>
<insert id="insertUserInfo" parameterType="com.test.entity.User">
INSERT INTO t_user(name, age, gender) VALUES (#{userName},#{age},#{gender})
<selectKey resultType="int" keyProperty="id">
SELECT LAST_INSERT_ID();
</selectKey>
</insert>
</mapper>
關于 *Mapper.xml 文件的配置,詳情參考官方文檔 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
通過服務調用
已經完成上述配置和接口等編寫后,就可以在服務中調用了。
@Service(value = "userService")
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public List<User> getUser(Integer id) {
List x = userMapper.findUserById(id);
return x;
}
@Override
public Integer addUser(User user) {
return userMapper.insertUser(user);
}
}
在系統設計時,不會讓服務直接就去調用如此底層的操作,往往會增加一個 model 層或者 controller 層。調用方法還是一致的,都是先注入 Mapper 接口,然后調用接口方法就可以了。
參考資料
- MyBatis 與 Spring 集成,官網 http://www.mybatis.org/spring/zh/getting-started.html
- MyBatis 官網,配置和使用介紹,http://www.mybatis.org/mybatis-3/zh/configuration.html
- SSM框架——詳細整合教程(Spring+SpringMVC+MyBatis),作者 shu_lin,http://blog.csdn.net/zhshulin/article/details/37956105