一、Mybatis相關(guān)概念
-
對(duì)象 / 關(guān)系數(shù)據(jù)庫(kù)映射(ORM)
- ORM全稱 Object Relation Mapping:表示對(duì)象 - 關(guān)系映射的縮寫(xiě)
- ORM完成?向?qū)ο蟮木幊陶Z(yǔ)?到關(guān)系數(shù)據(jù)庫(kù)的映射
當(dāng)ORM框架完成映射后,程序員既可以利??向?qū)ο蟪绦蛟O(shè)計(jì)語(yǔ)?的簡(jiǎn)單易?性剩彬,?可以利?關(guān)系數(shù)據(jù)庫(kù)的技術(shù)優(yōu)勢(shì)。 - ORM把關(guān)系數(shù)據(jù)庫(kù)包裝成?向?qū)ο蟮哪P?br> ORM框架是?向?qū)ο笤O(shè)計(jì)語(yǔ)?與關(guān)系數(shù)據(jù)庫(kù)發(fā)展不同步時(shí)的中間解決?案。采?ORM框架后,應(yīng)?程序不再直接訪問(wèn)底層數(shù)據(jù)庫(kù)道批,?是以?向?qū)ο蟮男问絹?lái)操作持久化對(duì)象,?ORM框架則將這些?向?qū)ο蟮牟僮鬓D(zhuǎn)換成底層SQL操作
- ORM框架實(shí)現(xiàn)的效果:把對(duì)持久化對(duì)象的保存入撒、修改隆豹、刪除等操作,轉(zhuǎn)換為對(duì)數(shù)據(jù)庫(kù)的操作
-
Mybatis簡(jiǎn)介
- MyBatis是?款優(yōu)秀的基于ORM的半?動(dòng)輕量級(jí)持久層框架茅逮,它?持定制化SQL璃赡、存儲(chǔ)過(guò)程以及?級(jí)映射
- MyBatis避免了?乎所有的JDBC代碼和?動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集
- MyBatis可以使?簡(jiǎn)單的XML或注解來(lái)配置和映射原?類型判哥、接?和Java的POJO (Plain Old Java Objects,普通?式Java對(duì) 象)為數(shù)據(jù)庫(kù)中的記錄。
-
Mybatis歷史
- 原是 apache 的?個(gè)開(kāi)源項(xiàng)? iBatis
- 2010年6?這個(gè)項(xiàng)?由apache software foundation 遷移到了google code碉考,隨著開(kāi)發(fā)團(tuán)隊(duì)轉(zhuǎn)投Google Code旗下塌计,ibatis3.x正式更名為Mybatis ,代碼于2013年11
?遷移到Github - iBATIS?詞來(lái)源于“internet”和“abatis”的組合豆励,是?個(gè)基于Java的持久層框架
- iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAO)
-
Mybatis優(yōu)勢(shì)
Mybatis是?個(gè)半?動(dòng)化的持久層框架夺荒,對(duì)開(kāi)發(fā)?員開(kāi)說(shuō)瞒渠,核?sql還是需要??進(jìn)?優(yōu)化良蒸,sql和java編碼進(jìn)?分離,功能邊界清晰伍玖,?個(gè)專注業(yè)務(wù)嫩痰,?個(gè)專注數(shù)據(jù)
二、Mybatis基本應(yīng)用
-
快速入門(mén)
- MyBatis官?地址:http://www.mybatis.org/mybatis-3/
- 開(kāi)發(fā)步驟
- 添加MyBatis的坐標(biāo)
- 創(chuàng)建user數(shù)據(jù)表
- 編寫(xiě)User實(shí)體類
- 編寫(xiě)映射文件 UserMapper.xml
- 編寫(xiě)核心文件 SqlMapConfig.xml
- 編寫(xiě)測(cè)試類
- 環(huán)境搭建
- 導(dǎo)?MyBatis的坐標(biāo)和其他相關(guān)坐標(biāo)
<?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.wujun</groupId> <artifactId>mybatis_quick_start</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>11</java.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <org.mybatis.mybatis>3.4.5</org.mybatis.mybatis> <mysql.mysql-connector-java>5.1.6</mysql.mysql-connector-java> <org.projectlombok.lombok.version>1.18.10</org.projectlombok.lombok.version> <com.alibaba.fastjson>1.2.4</com.alibaba.fastjson> <junit.junit>4.12</junit.junit> <log4j.log4j>1.2.12</log4j.log4j> </properties> <!--引入依賴--> <dependencies> <!--mybatis坐標(biāo)--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${org.mybatis.mybatis}</version> </dependency> <!--mysql驅(qū)動(dòng)坐標(biāo)--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.mysql-connector-java}</version> <scope>runtime</scope> </dependency> <!--單元測(cè)試坐標(biāo)--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.junit}</version> </dependency> <!--?志坐標(biāo)--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.log4j}</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${org.projectlombok.lombok.version}</version> <scope>provided</scope> </dependency> <!--fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${com.alibaba.fastjson}</version> </dependency> </dependencies> </project>
- 創(chuàng)建user數(shù)據(jù)表
CREATE TABLE `user` ( `id` bigint(20) NOT NULL, `username` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) )
- 編寫(xiě)User實(shí)體
package com.wujun.pojo; import lombok.Data; @Data public class User { private Long id; private String username; }
- 編寫(xiě)映射文件 UserMapper.xml
mapper標(biāo)簽的加載方式有4種:- 使用相對(duì)于類路徑的資源引用
例如:<mapper resource="org/mybatis/builder/AuthorMapper.xml"/> - 使?完全限定資源定位符(URL)
例如:<mapper url="file:///var/mappers/AuthorMapper.xml"/> - 使?映射器接口實(shí)現(xiàn)類的完全限定類名
例如:<mapper class="org.mybatis.builder.AuthorMapper"/> - 將包內(nèi)的映射器接?實(shí)現(xiàn)全部注冊(cè)為映射器
例如:<package name="org.mybatis.builder"/>
- 使用相對(duì)于類路徑的資源引用
<?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:名稱空間窍箍,與id組成sql的唯一標(biāo)識(shí)--> <mapper namespace="user"> <select id="findAll" resultType="com.wujun.pojo.User"> select * from User </select> </mapper>
- 編寫(xiě)核心文件 SqlMapConfig.xml
- 事務(wù)管理器(transactionManager)類型有兩種:
- JDBC:這個(gè)配置就是直接使?了JDBC 的提交和回滾設(shè)置串纺,它依賴于從數(shù)據(jù)源得到的連接來(lái)管理事務(wù)作用域
- MANAGED:這個(gè)配置幾乎沒(méi)做什么,它從來(lái)不提交或回滾?個(gè)連接椰棘,而是讓容器來(lái)管理事務(wù)的整個(gè)生命周期(比如 JEE 應(yīng)?服務(wù)器的上下文)纺棺。 默認(rèn)情況下它會(huì)關(guān)閉連接,然而?些容器并不希望這樣邪狞,因此需要將 closeConnection 屬性設(shè)置為 false 來(lái)阻止它默認(rèn)的關(guān)閉行為
- 數(shù)據(jù)源(dataSource)類型有三種
- UNPOOLED:這個(gè)數(shù)據(jù)源的實(shí)現(xiàn)只是每次被請(qǐng)求時(shí)打開(kāi)和關(guān)閉連接
- POOLED:這種數(shù)據(jù)源的實(shí)現(xiàn)利用“池”的概念將 JDBC 連接對(duì)象組織起來(lái)
- JNDI:這個(gè)數(shù)據(jù)源的實(shí)現(xiàn)是為了能在如 EJB 或應(yīng)?服務(wù)器這類容器中使用祷蝌,容器可以集中或在外部配置數(shù)據(jù)源,然后放置?個(gè) JNDI 上下文的引用
- 事務(wù)管理器(transactionManager)類型有兩種:
<?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> <!-- environments:運(yùn)行環(huán)境 --> <environments default="dev"> <!-- 一個(gè)environment代表一個(gè)環(huán)境帆卓,可以配置多個(gè)環(huán)境巨朦,例如[dev][test][prod]--> <environment id="dev"> <!--當(dāng)前事務(wù)交由JDBC進(jìn)行管理--> <transactionManager type="JDBC"></transactionManager> <!-- POOLED表示當(dāng)前使用mybatis提供的數(shù)據(jù)庫(kù)連接池 UNPOOLED表示不使用連接池,每次請(qǐng)求都會(huì)新建一個(gè)數(shù)據(jù)庫(kù)連接 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///wujun_test"/> <property name="username" value="wujun"/> <property name="password" value="wujun@2020"/> </dataSource> </environment> </environments> <!-- 引入映射配置文件 --> <mappers> <mapper resource="UserMapper.xml"></mapper> </mappers> </configuration>
- 編寫(xiě)測(cè)試類
package com.wujun.test; import com.wujun.pojo.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; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatisTest { @Test public void test1() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> users = sqlSession.selectList("user.findAll"); for (User user : users) { System.out.println(user); } sqlSession.close(); } }
- 返回結(jié)果
User(id=1, username=吳俊1) User(id=2, username=吳俊2) User(id=3, username=吳俊3)
三剑令、注意事項(xiàng)
執(zhí)行方法SqlSession sqlSession = sqlSessionFactory.openSession();
的時(shí)候糊啡,會(huì)默認(rèn)開(kāi)啟一個(gè)事務(wù),但是不會(huì)自動(dòng)提交該事務(wù)吁津,在執(zhí)行增刪改操作的時(shí)候棚蓄,需要手動(dòng)提交事務(wù)sqlSession.commit();
如果不想手動(dòng)提交事務(wù),則可以使用SqlSession sqlSession = sqlSessionFactory.openSession(true);
方法碍脏,該方法會(huì)自動(dòng)提交事務(wù)梭依。
四、Mybatis的Dao層傳統(tǒng)開(kāi)發(fā)方式
- 編寫(xiě)Dao層接口
package com.wujun.dao;
import com.wujun.pojo.User;
import java.io.IOException;
import java.util.List;
public interface IUserDao {
List<User> findAll() throws IOException;
}
- 編寫(xiě)Dao層實(shí)現(xiàn)類
package com.wujun.dao;
import com.wujun.pojo.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;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class UserDaoImpl implements IUserDao {
@Override
public List<User> findAll() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("user.findAll");
sqlSession.close();
return users;
}
}
- 編寫(xiě)測(cè)試類
package com.wujun.test;
import com.wujun.dao.IUserDao;
import com.wujun.dao.UserDaoImpl;
import com.wujun.pojo.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;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
/*@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("user.findAll");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}*/
@Test
public void test2() throws IOException {
IUserDao userDao = new UserDaoImpl();
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}
}
- 測(cè)試結(jié)果
User(id=1, username=吳俊1)
User(id=2, username=吳俊2)
User(id=3, username=吳俊3)
五潮酒、Mybatis的Dao層代理開(kāi)發(fā)方式
-
代理開(kāi)發(fā)方式介紹
- 采用 Mybatis 的代理開(kāi)發(fā)方式實(shí)現(xiàn) DAO 層的開(kāi)發(fā)睛挚,這種方式是主流。
- Mapper 接口開(kāi)發(fā)方法只需要程序員編寫(xiě)Mapper 接口(相當(dāng)于Dao 接口)急黎,由Mybatis 框架根據(jù)接口定義創(chuàng)建接口的動(dòng)態(tài)代理對(duì)象扎狱,代理對(duì)象的方法體同上邊Dao接口實(shí)現(xiàn)類方法
- Mapper 接?開(kāi)發(fā)需要遵循以下規(guī)范
- Mapper.xml文件中的namespace與mapper接口的全限定名相同
- Mapper接口方法名和Mapper.xml中定義的每個(gè)statement的id相同
- Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql的parameterType的類型相同
- Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql的resultType的類型相同
- 編寫(xiě) UserMapper 接?
public interface UserMapper {
List<User> findAll();
User findById(Long id);
}
- 重寫(xiě) UserMapper.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">
<!--namespace:名稱空間侧到,與id組成sql的唯一標(biāo)識(shí)-->
<mapper namespace="com.wujun.mapper.UserMapper">
<select id="findAll" resultType="com.wujun.pojo.User">
select * from User
</select>
<select id="findById" parameterType="java.lang.Long" resultType="com.wujun.pojo.User">
select * from User where id = #{id}
</select>
</mapper>
- 編寫(xiě)測(cè)試類
package com.wujun.test;
import com.wujun.dao.IUserDao;
import com.wujun.dao.UserDaoImpl;
import com.wujun.mapper.UserMapper;
import com.wujun.pojo.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;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
/*@Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("user.findAll");
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}*/
/*@Test
public void test2() throws IOException {
IUserDao userDao = new UserDaoImpl();
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
}*/
@Test
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
System.out.println("===============================");
User byId = mapper.findById(1L);
System.out.println(byId);
}
}
- 測(cè)試結(jié)果
User(id=1, username=吳俊1)
User(id=2, username=吳俊2)
User(id=3, username=吳俊3)
===============================
User(id=1, username=吳俊1)