主要內容:
- What is MyBatis?
- Why MyBatis?
- Installing and configuring MyBatis
- Sample domain model
What is MyBaits?
MyBatis是一個開源持久化框架频伤,用于簡化持久層的實現(xiàn)可很。Mybatis可以減少很多JDBC相關的模板樣式代碼伴鳖,還提供了方便使用的數(shù)據(jù)庫API屯伞。
MyBatis發(fā)展自iBATIS芜辕,但是MyBatis 3對iBATIS進行了徹底的重構律杠,從而可以使用注解(annotations)和映射器(Mappers)第岖。
簡潔的設計和易用性使得MaBatis在J2EE開發(fā)中很快流行起來难菌。在Java應用中,持久層的工作包括:將SQL語句從數(shù)據(jù)庫中查詢出的數(shù)據(jù)填充進Java對象中蔑滓、使用SQL語句將Java對象中的數(shù)據(jù)保存進數(shù)據(jù)庫郊酒。
MyBatis提供了下列特性來簡化SQL查詢:(1)抽象底層的JDBC代碼遇绞;(2)自動將SQL查詢的結果集保存進對應的Java對象;(3)從Java對象中提取數(shù)據(jù)并存入數(shù)據(jù)庫中對應的表燎窘。
ORM模型就是數(shù)據(jù)庫的表和簡單Java對象(Plain Ordinary Java Object摹闽,簡稱POJO)的映射關系模型,它主要解決數(shù)據(jù)庫數(shù)據(jù)和POJO對象的映射褐健。
Why MyBatis?
企業(yè)級應用開發(fā)領域有很多持久化開發(fā)框架冯遂,MyBatis能夠脫穎而出的原因在于:
- 減少了很多JDBC的模板樣式代碼蝌数;
- 學習曲線低;
- 可以很好地適配遺留數(shù)據(jù)庫;
- 開發(fā)者需要自己寫SQL語句盐肃;
- 可以和Spring湿右、Guice等框架整合使用笆豁;
- 支持第三方緩存庫震嫉;
- 具備良好的性能。
減少JDBC的模板樣式代碼
關于JDBC代碼的冗長刹帕,可以參考Spring實戰(zhàn)6-利用Spring和JDBC訪問數(shù)據(jù)庫一文中用過的例子吵血。
直接使用JDBC的API,會有很多重復代碼:創(chuàng)建連接偷溺、創(chuàng)建statement蹋辅、設置輸入?yún)?shù),最后還需要關閉資源挫掏。MyBatis將這些通用功能抽象出來單獨完成晕翠,以便開發(fā)者可以專注于真正重要的事情,包括書寫SQL語句砍濒、構建Java對象等淋肾。
除了這些,MyBatis可以自動完成兩個工作:把Java對象中的屬性設置進SQL字符串的查詢參數(shù)爸邢、利用SQL查詢結果集的數(shù)據(jù)構造Java對象樊卓。實現(xiàn)方法如下:
- 在SQL Mapper配置文件中(StudentMapper.xml)配置查詢語句
<select id="findStudentById" parameterType="int" resultType="Student">
SELECT STUD_ID AS studId, NAME , EMAIL, DOB
FROM STUDENTS WHERE STUD_ID=#{Id}
</select>
<insert id="insertStudent" parameterType="Student">
INSERT INTO STUDENTS(STUD_ID, NAME, EMAIL, DOB)
VALUES (#{studId}, #{name}, #{email}, #{dob})
</insert>
- 創(chuàng)建StudentMapper接口
public interface StudentMapper {
Student findStudentById(Integer id);
void insertStudent(Student student);
}
- 在Java代碼中的用法如下
SqlSession session = getSqlSessionFactory().openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
// select Student by Id
Student student = mapper.selectStudentById(1);
// To insert a Student record
mapper.insertStudent(student);
可以看出,如果使用MyBatis框架杠河,開發(fā)者不需要自己管理資源和處理異常碌尔,因為MyBatis會替你完成這些工作。除此之外券敌,MyBatis還提供了其他特性唾戚,也可以簡化持久層的實現(xiàn):
- 支持復雜SQL結果集到復雜對象的映射;
- 支持1-1和1-n映射待诅,將結果集中的數(shù)據(jù)映射到Java對象中叹坦;
- 支持基于輸入數(shù)據(jù)構建動態(tài)SQL查詢。
學習曲線低
MyBatis的學習曲線很低卑雁,如果開發(fā)者之前熟悉Java和SQL開發(fā)募书,則只需要稍作學習就可以在項目中使用MyBatis绪囱。
可以很好地適配遺留數(shù)據(jù)庫
有時候,我們需要使用不規(guī)范的遺留數(shù)據(jù)庫莹捡。在維護老服務時經(jīng)常遇到這種情況鬼吵,使用類似Hibernate的ORM框架會非常麻煩,因為這類框架試圖將Java對象映射到數(shù)據(jù)庫中的表格里篮赢。
MyBatis可以自動將查詢結果映射到Java對象中齿椅,這個特性使得MyBatis非常適合使用遺留數(shù)據(jù)庫。
擁抱SQL語句
完全的ORM框架启泣,例如Hibernate鼓勵開發(fā)者直接使用實體對象涣脚,而由框架自動產(chǎn)生SQL語句。正因如此种远,導致開發(fā)者不能使用特定數(shù)據(jù)庫的優(yōu)化特性涩澡。Hibernate也允許開發(fā)者寫SQL語句顽耳,但這又違背了“持久層應該與數(shù)據(jù)庫獨立”的承諾坠敷。
MyBatis讓開發(fā)者自己寫SQL語句,因此可以利用特定數(shù)據(jù)庫的優(yōu)化特性射富,例如支持使用數(shù)據(jù)庫存儲過程膝迎。
支持使用第三方緩存庫
MyBatis本身支持在SqlSession層面緩存SELECT查詢結果。除此之外胰耗,MyBatis也支持使用其他第三方緩存限次,例如EHCache、OSCache和Hazelcast柴灯。
更好的性能
大型企業(yè)級應用必須具備良好的性能卖漫。在性能分析時,一般使用調用鏈路分析法:業(yè)務操作赠群、緩存操作和持久層羊始。持久層的性能經(jīng)常會成為應用的性能瓶頸。
- MyBatis支持使用數(shù)據(jù)庫連接池查描,從而避免為每個查詢請求創(chuàng)建數(shù)據(jù)庫連接突委;
- MyBatis擁有內置的緩存機制,可以在SqlSession層面緩存SQL查詢的結果——如果你在執(zhí)行一個select查詢之后不久又再次遇到同樣的請求冬三,則直接返回緩存區(qū)中的數(shù)據(jù)匀油,從而節(jié)省一次數(shù)據(jù)庫查詢。
- MyBatis并沒有大量使用代理勾笆,因此比其他大量使用代理的ORM框架有更好的性能敌蚜。
注意:在軟件開發(fā)中沒有萬能的工具。每個應用場景都有不同的需求窝爪,我們應該根據(jù)具體的應用場景選擇要使用的語言和框架钝侠。上文中講了很多MyBatis的優(yōu)勢该园,不過,也有一些情況下并不適合使用MyBatis帅韧。如果應用是基于對象模型驅動并想動態(tài)生成SQL語句里初;另外,如果開發(fā)者希望在應用中使用透明的事務處理機制(持久化父對象的同時也持久化與之關聯(lián)的子對象)忽舟,這兩種情況下都比較適合使用Hibernate双妨。
安裝和配置MyBatis
- 在數(shù)據(jù)庫中創(chuàng)建students表,并插入例子數(shù)據(jù)叮阅;
create table students
(
stud_id int(11) not null auto_increment,
name varchar(50) not null,
email varchar(50) not null,
dob date default null,
primary key (stud_id)
) engine=InnoDB auto_increment=1 default charset=latin1;
insert into students(stud_id, name, email, dob)
values(1, 'Student1', 'student1@gmail.com', '1983-06-25');
insert into students(stud_id, name, email, dob)
values(2, 'Student2', 'student2@gmail.com', '1983-06-25');
- 創(chuàng)建一個maven項目刁品,配置jar依賴項,pom文件的內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.javadu</groupId>
<artifactId>leanMybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>2.0.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.2.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.13</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.13</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
然后浩姥,在resources目錄下創(chuàng)建log4j.properties文件挑随,填入如下內容:
log4j.rootLogger = DEBUG, stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d[%-5p] %c - %m%n
- 創(chuàng)建mybatis-config.xml和StudentMapper.xml配置文件,mybatis-config.xml作為MyBatis的主配置文件勒叠,用于定義數(shù)據(jù)庫連接兜挨、類型別名等等;StudentMapper.xml配置文件包含操作students表的SQL語句眯分。
- 首先拌汇,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>
<typeAliases>
<typeAlias type="com.javadu.domain.Student" alias="Student" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis/mappers/StudentMapper.xml" />
</mappers>
</configuration>
- 然后,StudentMapper.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="mybatis.mappers.StudentMapper">
<resultMap id="studentResult" type="Student">
<id property="studId" column="sutd_id" />
<result property="name" column="name" />
<result property="email" column="email" />
<result property="dob" column="dob" />
</resultMap>
<select id="findAllStudents" resultMap="studentResult">
SELECT * FROM students
</select>
<select id="findStudentById" parameterType="int" resultType="Student">
SELECT stud_id as studid, name, email, dob
FROM students
WHERE stud_id=#{id}
</select>
<insert id="insertStudent" parameterType="Student">
INSERT INTO students(stud_id, name, email, dob)
VALUES (#{studId}, #{name}, #{email}, #{dob})
</insert>
</mapper>