傳統JDBC編程存在的弊端
1)工作量大,操作數據庫至少要5步
1.加載JDBC驅動Class.forName("com.mysql.jdbc.Driver");
2.與數據庫建立連接DriverManager.getConnection(url,uname,pwd);
3.獲取操作對象,發送sql語句得到返回結果
4.處理返回結果
5.釋放資源.close()
2)業務代碼和技術代碼耦合
3)連接資源手動關閉,帶來隱患
框架概述
MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注SQL本身,而不需要花費精力去處理例如註冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。它使用ORM的思想實現了結果集的封裝。
MyBatis通過xml或註解的方式將要執行的各種statement配置起來,並通過java對象和statement中sql的動態參數進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射爲java對象並返回。
三層框架:
表現層: 用於展示數據
業務層: 處理業務需求
持久層:和數據庫進行交互
ORM思想
ORM(Object Relational Mapping)模型就是數據庫表與簡單Java對象(POJO)的映射模型,它主要解決數據庫數據和Java實體對象的相互映射。
ORM工具的唯一作用就是:把對持久化對象的保存、修改、刪除等操作,轉換成對數據庫的操作。由此,程序員可以以面向對象的方式操作持久化對象,而ORM框架則負責將相關操作轉換成對應的SQL(結構化查詢語言)操作。
ORM帶來的好處:
1)更加貼合面向對象的編程語義,Java程序員喜歡的姿勢;
2)技術和業務解耦
3)自動釋放數據庫連接資源
MyBatis入門
概述
mybatis是一個持久層框架,用java編寫的。它封裝了jdbc操作的很多細節,使開發者只需要關注sql語句本身,而無需關注註冊驅動,創建連接等繁雜過程。它使用了ORM思想實現了結果集的封裝。
mybatis的環境搭建-使用xml文件
第一步:創建maven工程並導入座標,在pom.xml中添加Mybatis框架所需要依賴的座標(jar包)
<?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.lwl</groupId>
<artifactId>MyBatis</artifactId>
<version>1.0-SNAPSHOT</version>
<!--打包方式-->
<packaging>jar</packaging>
<!--定位相關依賴-->
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
</project>
第二步:創建實體類和dao的接口。
public interface IUserDao {
/**
* 查詢所有操作
* @return
*/
List<User> findAll();
}
第三步:創建Mybatis的主配置文件 SqlMapConifg.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">
<!--Mybatis主配置文件-->
<configuration>
<!--配置環境-->
<environments default="mysql">
<!--配置mysql環境-->
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!--配置連接池-->
<dataSource type="POOLED">
<!--配置連接數據庫的四個基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/user"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</dataSource>
</environment>
</environments>
<!--使用resource指定映射配置文件的位置,映射配置文件指的是每個dao獨立的配置文件-->
<mappers>
<mapper resource="com/lwl/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
第四步:創建映射配置文件 IUserDao.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="com.lwl.dao.IUserDao">
<!--select爲SQL中的關鍵詞,id對應類中查詢的函數名稱,resultType中填寫被封裝的類的全類名-->
<select id="findAll" resultType="com.lwl.domain.User">
</select>
</mapper>
環境搭建的注意事項:
1. 創建IUserDao.xml 和 IUserDao.java時名稱是爲了和之前的知識保持一致。
在Mybatis中它把持久層的操作接口名稱和映射文件也叫做:Mapper
所以在其他項目中:IUserDao 和 IUserMapper是一樣的
2. 在idea中創建目錄的時候,它和包是不一樣的
包在創建時:com.itheima.dao它是三級結構
目錄在創建時:com.itheima.dao是一級目錄
3. mybatis的映射配置文件位置必須和dao接口的包結構相同
4. 映射配置文件的mapper標籤namespace屬性的取值必須是dao接口的全限定類名
5. 映射配置文件的操作配置(select),id屬性的取值必須是dao接口的方法名
測試
進行查詢操作,在IUserDao.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="com.lwl.dao.IUserDao"> <!-- 填寫需要映射的Dao -->
<!--配置查詢所有-->
<!--id與接口關聯,resultType與要封裝的實體對應-->
<select id="findAll" resultType="com.lwl.domain.User">
select * from user;
</select>
</mapper>
新建測試類進行查詢:
第一步:讀取配置文件
第二步:創建SqlSessionFactory工廠
第三步:創建SqlSession
第四步:創建Dao接口的代理對象
第五步:執行dao中的方法
第六步:釋放資源
package com.lwl.test;
import com.lwl.dao.IUserDao;
import com.lwl.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import javax.annotation.Resources;
import java.io.InputStream;
import java.util.List;
/**
* @author liwenlong
* @data 2020/5/3
*/
public class MybatisTest {
@Test
public void test() throws Exception{
//1.讀取配置文件
InputStream is = Resources.class.getResourceAsStream("/SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工廠生產SqlSessionFactory對象
SqlSession session = factory.openSession();
//4.使用SqlSession的實例創建Dao接口的代理對象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用動態代理執行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//6.釋放資源
session.close();
is.close();
}
}
輸出結果:
mybatis的環境搭建-使用註解
重新使用註解的形式再進行一遍,這次不再使用 IUserDao.xml。
方法:
把IUserDao.xml移除,在dao接口的方法上使用@Select註解,並且指定SQL語句
同時需要在SqlMapConfig.xml中的mapper配置時,使用class屬性指定dao接口的全限定類名。
步驟:
第一步和使用xml方式相同:創建maven工程並導入座標,在pom.xml中添加Mybatis框架所需要依賴的座標(jar包)
<?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.lwl</groupId>
<artifactId>MyBatis</artifactId>
<version>1.0-SNAPSHOT</version>
<!--打包方式-->
<packaging>jar</packaging>
<!--定位相關依賴-->
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
</project>
第二步:創建實體類和dao的接口,和之前的區別是增加註解。
public interface IUserDao {
/**
* 查詢所有操作
* @return
*/
//加上註解
@Select("select * from user")
List<User> findAll();
}
第三步:創建Mybatis的主配置文件 SqlMapConifg.xml (數據庫連接和指定映射配置文件的位置[目的是爲了不用自己實現數據庫查詢方法])
和xml配置方式的區別是在指定映射配置文件的位置的時候,應該使用class屬性指定被註解的dao權限定類名。
<?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">
<!--Mybatis主配置文件-->
<configuration>
<!--配置環境-->
<environments default="mysql">
<!--配置mysql環境-->
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<!--配置連接池-->
<dataSource type="POOLED">
<!--配置連接數據庫的四個基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/user"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,應該使用class屬性來指定備註接的dao權限定類名-->
<mappers>
<mapper class="com.lwl.dao.IUserDao"></mapper>
</mappers>
</configuration>
測試
還是使用之前寫的測試類:
package com.lwl.test;
import com.lwl.dao.IUserDao;
import com.lwl.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import javax.annotation.Resources;
import java.io.InputStream;
import java.util.List;
/**
* @author liwenlong
* @data 2020/5/3
*/
public class MybatisTest {
@Test
public void test() throws Exception{
//1.讀取配置文件
InputStream is = Resources.class.getResourceAsStream("/SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3.使用工廠生產SqlSessionFactory對象
SqlSession session = factory.openSession();
//4.使用SqlSession的實例創建Dao接口的代理對象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用動態代理執行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//6.釋放資源
session.close();
is.close();
}
}
輸出的結果和xml文件配置方式輸出的結果一樣。
不管使用XML還是註解配置,我們在實際開發中,都是越簡便越好,所以都是採用不寫dao實現類的方式。但是Mybatis它是支持寫dao實現類的。
代碼分析
測試類
1. 讀取配置文件
InputStream is = Resources.class.getResourceAsStream("/SqlMapConfig.xml");
路徑分爲絕對路徑和相對路徑,但是使用絕對路徑的話,在本地的文件位置就不能發生變動,否則會出錯。使用相對路徑的話,當項目被部署之後,src等目錄就會消失。因此在實際開發項目中,兩種都不會使用,而是使用以下兩種:
第一個:使用類加載器,他只能讀取類路徑的配置文件
第二個:使用ServletContext對象的getRealPath()
2.創建SqlSessionFactory工廠,使用工廠創建對象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
SqlSession session = factory.openSession();
創建工廠MyBatis使用了 構建者模式 , 把對象的創建細節隱藏,使用者直接調用方法就可以得到對象。
3.使用SqlSession的實例創建Dao接口的代理對象
IUserDao userDao = session.getMapper(IUserDao.class);
mybatis在使用代理dao的方式實現增刪改查時只做兩件事,
第一:創建代理對象
第二:在代理對象中調用selectList
主配置文件
主要包含數據庫配置信息:
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/user"></property>
<property name="username" value="root"></property>
<property name="password" value="1234"></property>
映射配置信息,其中包含執行SQL的語句,可以獲取PreparedStatement,並且需要包括全類名。
<?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.lwl.dao.IUserDao"> <!-- 填寫需要映射的Dao -->
<!--配置查詢所有-->
<!--id與接口關聯,resultType與要封裝的實體對應-->
<select id="findAll" resultType="com.lwl.domain.User">
select * from user;
</select>
</mapper>
程序中讀取配置文件:用到的技術就是解析xml的技術,此處使用dom4j解析xml技術。
此部分相當於在JDBC中根據配置文件的信息創建Connection對象,註冊驅動,獲取PreparedStatement連接對象。而PreparedStatement對象需要SQL語句,SQL語句就從解析的XML文件中獲取。
接下來該執行查詢操作,查詢出結果集,然後對結果集進行遍歷封裝成對象。
而在MyBatis中藥封裝成對象就要先得到這個對象,就是在xml文件中的resultType來指定將要封裝成的對象的位置。由於創建的類中屬性名稱和表的列名是一直的,我們可以將表的列名看成是實體類的屬性名稱,通過反射的方式來根據名稱獲取每個屬性,並賦值到這個對象中。
如果想要像JDBC那樣執行,就需要兩個信息,一個是連接信息,另外一個映射信息。連接信息就是連接數據庫需要的四個基本要素。映射信息需要包括執行的SQL語句和被封裝類的權限定類名。因此在MyBatis中在解析xml的過程中,將SQL語句和被封裝類的權限定類名封裝成一個對象進行獲取,可以使用一個Mapper類進行封裝。