前言
MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以對(duì)配置和原生Map使用簡(jiǎn)單的 XML 或注解,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫(kù)中的記錄。
—— 摘自 MyBatis 中文官網(wǎng),http://www.mybatis.org/mybatis-3/zh/
Spring 與 MyBatis 集成
MyBatis 與 Spring 的集成思路,總共有以下幾個(gè)步驟:
- 引入 MyBatis 與 Spring 框架相關(guān)的包,數(shù)據(jù)庫(kù)驅(qū)動(dòng)的包,可引入數(shù)據(jù)庫(kù)連接池、日志、測(cè)試相關(guān)包
- 配置XML,包括數(shù)據(jù)源 DataSource (用于指定數(shù)據(jù)庫(kù)連接地址、賬號(hào)、密碼等數(shù)據(jù)庫(kù)配置)和 SqlSessionFactory (用于指定 MyBatis 自動(dòng)載入的 *Mapper.xml)
- 編寫(xiě) Entity 類,用來(lái)存儲(chǔ)數(shù)據(jù)庫(kù)查詢返回?cái)?shù)據(jù),一般而言,成員變量對(duì)應(yīng)數(shù)據(jù)庫(kù)表字段名,僅提供 getter/setter 方法
- 編寫(xiě) Mapper 接口 與 Mapper.xml ,Mapper 接口 指定操作名,并規(guī)定好傳入?yún)?shù),Mapper.xml 為數(shù)據(jù)庫(kù)操作的 SQL ,id 需要與 Mapper 接口 一致
- 創(chuàng)建數(shù)據(jù)庫(kù),編寫(xiě)服務(wù),測(cè)試
一、Maven 引入 jar 包
在 Maven 項(xiàng)目中的 pom.xml 文件增加以下依賴。項(xiàng)目一般還需要增加 log 日志模塊、junit 測(cè)試模塊等,在此 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>
二、創(chuàng)建數(shù)據(jù)庫(kù)環(huán)境
因?yàn)?MyBatis 框架是解決持久化或者說(shuō)數(shù)據(jù)庫(kù)的問(wèn)題,因此我們需要配置一下數(shù)據(jù)庫(kù)環(huán)境。
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 ,至少需要一個(gè) SqlSessionFactoryBean 是用于創(chuàng)建 SqlSessionFactory 的。要配置這個(gè) Factory bean ,放置下面的代碼在 Spring 的 XML 配置文件中。我在配置時(shí),將數(shù)據(jù)庫(kù)相關(guān)的配置都創(chuàng)建了一個(gè)獨(dú)立的 XML 配置文件,然后在 Spring 主配置文件中通過(guò) 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文件存放的位置,當(dāng)Mapper文件跟對(duì)應(yīng)的Mapper接口處于同一位置的時(shí)候可以不用指定該屬性的值 -->
<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" />
<!-- 掃描器開(kāi)始掃描的基礎(chǔ)包名,支持嵌套掃描 -->
<property name="basePackage" value="com.test.dao.mapper" />
</bean>
</beans>
以上是 my-db.xml 配置文件,主要分為三部分:
- datasource ,數(shù)據(jù)源,與數(shù)據(jù)庫(kù)連接相關(guān),配置數(shù)據(jù)庫(kù)的地址、賬戶、密碼,一些配置等等,從 jdbc.properties 文件中載入。關(guān)于 Spring 如何載入 properties 文件如何實(shí)現(xiàn),不在這篇文章贅述了。
- sqlSessionFactory ,數(shù)據(jù)庫(kù)會(huì)話工廠。從
*Mapper.xml中文件自動(dòng)載入<mapper> - Mapper 類 ,在此配置中采用 Scanner 方式,自動(dòng)從 mapper 包內(nèi)載入 mapper 類。
四、調(diào)用 MyBatis 框架
創(chuàng)建 Entity,映射 Database 表(或有)
在 entity 包中創(chuàng)建實(shí)體,對(duì)應(yīng) t_user 表 的返回。成員變量一般與數(shù)據(jù)庫(kù)表字段名一一對(duì)應(yīng),成員方法僅提供 getter/setter 方法。
實(shí)體類不是必須的,MyBatis 提供將數(shù)據(jù)庫(kù)返回簡(jiǎn)單的映射到 Map 或 HashMap 結(jié)構(gòu)中,而非 POJO 中。
/**
* t_user 表實(shí)體
*/
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; }
}
創(chuàng)建 DAO/Mapper
在 dao.mapper 包內(nèi)創(chuàng)建 UserMapper 接口 ,并添加 @Repository 注解
@Repository
public interface UserMapper {
public List<User> findUserById(int id);
public Integer insertUser(User user);
}
對(duì)應(yīng)具體數(shù)據(jù)庫(kù)的方法,例如插入用戶、通過(guò) id 查找用戶。每次需要定義一個(gè)數(shù)據(jù)庫(kù)操作,就在 Mapper 類中定義一個(gè)接口。
注意,因?yàn)樵谌⑴渲?sqlSessionFactory 與 DataSource ,定義了自動(dòng)載入 Mapper 類 。因此,需要加入了
@Repository的注解,用于標(biāo)注數(shù)據(jù)訪問(wèn)組件,即DAO 組件。否則不需要 @Repository 注解,但需要在*Mapper.xml中增加<mapper>配置。
配置 Mapper.xml
在 Mapper.xml 中編寫(xiě)具體的數(shù)據(jù)庫(kù)操作的 SQL。
其中,tag 有 insert, select, update 等
id 與 Mapper 接口方法名一一對(duì)應(yīng);
parameterType 為傳入?yún)?shù),可以是 POJO,也可以是 int、String 這種基本類型,SQL 中的參數(shù)用 #{id} 的形式表示;
resultType 或者 resultMap ,都是存儲(chǔ)返回的結(jié)果集,其中 resultMap 比較強(qiáng)大,靈活;resultType 可以簡(jiǎn)單指定為 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">
<!--配置一個(gè)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>
關(guān)于 *Mapper.xml 文件的配置,詳情參考官方文檔 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html
通過(guò)服務(wù)調(diào)用
已經(jīng)完成上述配置和接口等編寫(xiě)后,就可以在服務(wù)中調(diào)用了。
@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);
}
}
在系統(tǒng)設(shè)計(jì)時(shí),不會(huì)讓服務(wù)直接就去調(diào)用如此底層的操作,往往會(huì)增加一個(gè) model 層或者 controller 層。調(diào)用方法還是一致的,都是先注入 Mapper 接口,然后調(diào)用接口方法就可以了。
參考資料
- MyBatis 與 Spring 集成,官網(wǎng) http://www.mybatis.org/spring/zh/getting-started.html
- MyBatis 官網(wǎng),配置和使用介紹,http://www.mybatis.org/mybatis-3/zh/configuration.html
- SSM框架——詳細(xì)整合教程(Spring+SpringMVC+MyBatis),作者 shu_lin,http://blog.csdn.net/zhshulin/article/details/37956105