
架構分析
MyBatis 是支援普通 SQL 查詢,存儲過程和進階映射的優秀持久層架構。 MyBatis 消除了幾乎所有的 JDBC 代碼和參數的手工設定以及對結果集的檢索。MyBatis 可以使用簡單的XML 或注解用于配置和原始映射,将接口和 Java 的 POJO( Plain Old Java Objects,普通的Java 對象)映射成資料庫中的記錄。
該圖引用于51CTO
借助于該架構圖我們可以發現,Mybatis的功能架構分為三層:
(1)API接口層:提供給外部使用的接口API,開發人員通過這些本地API來操縱資料庫。接口層一接收到調用請求就會調用資料處理層來完成具體的資料處理。
(2)資料處理層:負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次資料庫操作。
(3) 基礎支撐層:負責最基礎的功能支撐,包括連接配接管理、事務管理、配置加載和緩存處理,這些都是共用的東西,将他們抽取出來作為最基礎的元件。為上層的資料處理層提供最基礎的支撐。
作為持久層架構,mybatis可以将程式中的大量sql語句剝離出來,配置在配置檔案中,實作sql的靈活配置。可以将sql語句和代碼分離,無需修改代碼,在配置檔案中修改配置檔案即可到達修改sql的目的。
開發人員面對的是純粹的java對象,和hibernate的orm思想一緻。但對于具體的資料操作,hibernate會自動生成sql語句,而mybatis使用的時候,需要開發人員編寫配置檔案,将sql所需要的參數和傳回的結果字段映射到具體的pojo。
maven依賴
為了友善,建構的是maven項目,需要的依賴分别有:
- junit (java單元測試依賴)
- mybatis(mybatis依賴)
- mysql (mysql資料庫依賴)
- log4j (日志資訊依賴)
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
建立資料庫
為了測試mybatis的功能,首先建立一個簡單的資料庫,比較簡單,資料庫字段含義不再贅述。
create database mybatis;
use mybatis;
CREATE TABLE `tb_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(18) DEFAULT NULL,
`sex` char(2) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
建立pojo對象
在這裡建立了一個非常簡單的pojo類,用于測試mybatis的功能。
/**
* fayuan.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.fayuan.domain;
/**
* 使用者類
*
* @author fayuan.fzw
* @version $Id: User.java, v 0.1 2018年02月18日 上午11:05 fayuan.fzw Exp $
*/
public class User {
/** id */
private int id;
/** 姓名 */
private String name;
/** 性别 */
private String sex;
/** 年齡 */
private int age;
public User(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
這個類其實就是一個普通的javaBean,mybatis使用pojo類作為持久化類,這也是mybatis低侵入設計的關鍵。mybatis不需要持久化類繼承任何父類,或者實作接口,可以保證代碼的無侵入無污染。
pojo和資料庫表字段映射
為了實作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">
<!-- namespace指使用者自定義的命名空間。 -->
<mapper namespace="com.fayuan.mapper.UserMapper">
<!--
id="save"是唯一的标示符
parameterType屬性指明插入時使用的參數類型
useGeneratedKeys="true"表示使用資料庫的自動增長政策
-->
<insert id="save" parameterType="com.fayuan.domain.User" useGeneratedKeys="true">
insert into tb_user (name,sex,age) VALUES (#{name},#{sex},#{age})
</insert>
<!-- select操作
parameterType="int"表示該查詢語句需要一個int類型的參數
resultType="user"表示傳回的是一個user對象 -->
<select id="select" parameterType="int" resultType="User">
select * from tb_user where id=#{id}
</select>
<!-- update操作
parameterType="user"表示該更新語句需要一個user對象作為參數-->
<update id="update" parameterType="User">
update tb_user set name= #{name},sex= #{sex},age=#{age} where id= #{id}
</update>
<!-- delete操作
parameterType="int"表示該查詢語句需要一個int類型的參數-->
<delete id="delete" parameterType="int">
delete from tb_user where id=#{id}
</delete>
</mapper>
在這裡一次性添加了增、删、查、改的映射關系,為了實作每一部分的功能,對于每一部分單獨寫一個測試類。
插入
/**
* Alipay.com Inc.
* Copyright (c) 2004-2018 All Rights Reserved.
*/
package com.fayuan.test;
import java.io.InputStream;
import com.fayuan.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/**
* 測試插入功能
*
* @author fayuan.fzw
* @version $Id: InsertTest.java, v 0.1 2018年02月19日 下午4:02 fayuan.fzw Exp $
*/
public class InsertTest {
public static void main(String[] args) throws Exception {
//讀取mybatis-config.xml檔案
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//初始化mybatis,建立SqlSessionFactory類的執行個體
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//建立Session執行個體
SqlSession sqlSession = sqlSessionFactory.openSession();
//建立User對象
User user = new User ("fayuan","男",24);
//插入資料
sqlSession.insert("com.fayuan.mapper.UserMapper.save", user);
//送出事務
sqlSession.commit();
//關閉session
sqlSession.close();
}
}
列印出來的日志:
DEBUG [main] - ==> Preparing: insert into tb_user (name,sex,age) VALUES (?,?,?)
DEBUG [main] - ==> Parameters: fayuan(String), 男(String), 24(Integer)
DEBUG [main] - <== Updates: 1
查找
/**
* fayuan.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.fayuan.test;
import com.fayuan.domain.User;
import com.fayuan.factory.SqlSessionFactoryClass;
import org.apache.ibatis.session.SqlSession;
/**
* 測試查找功能
*
* @author fayuan.fzw
* @version $Id: SelectTest.java, v 0.1 2018年02月24日 下午11:19 fayuan.fzw Exp $
*/
public class SelectTest {
public static void main(String[] args) {
//擷取Session執行個體
SqlSession sqlSession = SqlSessionFactoryClass.getSqlSession();
// 建立User對象
User user = sqlSession.selectOne("com.fayuan.mapper.UserMapper.select", 1);
System.out.println("name = " + user.getName() + ", sex = " + user.getSex() +", age = " + user.getAge());
//送出事務
sqlSession.commit();
//關閉Session
sqlSession.close();
}
}
列印出來的日志:
DEBUG [main] - ==> Preparing: select * from tb_user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
修改
/**
* fayuan.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.fayuan.test;
import com.fayuan.domain.User;
import com.fayuan.factory.SqlSessionFactoryClass;
import org.apache.ibatis.session.SqlSession;
/**
* 測試修改功能
* @author fayuan.fzw
* @version $Id: UpdateTest.java, v 0.1 2018年02月24日 下午11:03 fayuan.fzw Exp $
*/
public class UpdateTest {
public static void main(String[] args) {
//擷取Session執行個體
SqlSession sqlSession = SqlSessionFactoryClass.getSqlSession();
// 根據id查詢User對象
User user = sqlSession.selectOne("com.fayuan.mapper.UserMapper.select",1);
// 修改User對象的屬性值
user.setName("tom");
user.setAge(25);
// 修改User對象
sqlSession.update("update", user);
// 送出事務
sqlSession.commit();
// 關閉Session
sqlSession.close();
}
}
列印出來的日志:
DEBUG [main] - ==> Preparing: select * from tb_user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: update tb_user set name= ?,sex= ?,age=? where id= ?
DEBUG [main] - ==> Parameters: tom(String), ?(String), 25(Integer), 1(Integer)
DEBUG [main] - <== Updates: 1
删除
/**
* fayuan.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.fayuan.test;
import com.fayuan.factory.SqlSessionFactoryClass;
import org.apache.ibatis.session.SqlSession;
/**
* 測試删除功能
*
* @author fayuan.fzw
* @version $Id: DeleteTest.java, v 0.1 2018年02月24日 下午11:55 fayuan.fzw Exp $
*/
public class DeleteTest {
public static void main(String[] args) throws Exception {
// 獲得Session執行個體
SqlSession session = SqlSessionFactoryClass.getSqlSession();
// 删除id為1的User對象
session.delete("com.fayuan.mapper.UserMapper.delete", 1);
// 送出事務
session.commit();
// 關閉Session
session.close();
}
}
DEBUG [main] - ==> Preparing: delete from tb_user where id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Updates: 1
問題總結:
- 配置檔案位置聲明
- pojo需要加上無參構造,否則在内部的反射機制是無法獲得pojo對象的
- 使用log4j觀察執行狀況
- aliases的使用
- 其他配置(pool、别名......)
能讓一個男孩子熱血的,不僅有夢想,還有姑娘。