Mybatis框架(一)
1、JDBC訪問數(shù)據(jù)庫
JDBC是Sun公司為應(yīng)用程序與數(shù)據(jù)庫驅(qū)動之間提供的一組接口規(guī)范,它在操作數(shù)據(jù)庫的時候流程如下:
1、注冊驅(qū)動
2、建立連接
3、創(chuàng)建發(fā)送SQL語句的對象
4、發(fā)送SQL語句
5、對返回結(jié)果處理
6、資源釋放
使用JDBC操作數(shù)據(jù)庫存在種種問題:
1、頻繁的創(chuàng)建、釋放數(shù)據(jù)庫連接,資源浪費;
2、SQL語句與Java代碼在一塊,不易維護;
3、傳輸傳遞硬編碼問題;
4、結(jié)果集解析硬編碼問題;
這就不得不說Mybatis這樣一種持久層框架。mybatis針對JDBC出現(xiàn)的問題,都得到了很好的解決。
1、數(shù)據(jù)庫連接池;
2、SQL語句與Java代碼分離;
3、Mybatis自動將java對象映射至sql語句;
4、Mybatis自動將sql執(zhí)行結(jié)果映射至java對象;
2、Mybatis的簡單使用
2.1、Mybatis介紹
MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優(yōu)秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數(shù)的手工設(shè)置以及對結(jié)果集的檢索封裝。MyBatis可以使用簡單的XML或注解用于配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數(shù)據(jù)庫中的記錄。
2.2、Mybatis簡單使用
全局配置文件mybatis-config.xml
全局配置文件,是對MyBatis 的核心行為的控制。
數(shù)據(jù)庫配置文件db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springcloud01?serverTimezone=UTC
jdbc.username=root
jdbc.password=root
實體類文件
@Data
public class Employee {
private Integer eId;
private String eName;
private Date eInDate;
private Double eSalary;
private Integer dId;
}
接口文件
public interface EmployeeMapper {
//查詢員工信息
public List<Employee> searchEmps();
}
對象映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pyn.dao.EmployeeMapper">
<resultMap type="emp" id="myEmp1">
<id property="eId" column="eid" />
<result property="eName" column="ename" />
<result property="eInDate" column="eindate" />
<result property="eSalary" column="esalary" />
<result property="dId" column="did" />
</resultMap>
<!--searchEmps() 查詢所有員工信息-->
<select id="searchEmps" resultMap="myEmp1">
select * from employee
</select>
</mapper>
全局配置文件
<?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>
<!--引入數(shù)據(jù)庫配置文件-->
<properties resource="db.properties"></properties>
<settings>
<!-- 打印查詢語句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 控制全局緩存(二級緩存)-->
<setting name="cacheEnabled" value="true"/>
<!-- 延遲加載的全局開關(guān)。當(dāng)開啟時,所有關(guān)聯(lián)對象都會延遲加載。默認 false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 當(dāng)開啟時,任何方法的調(diào)用都會加載該對象的所有屬性。默認 false,可通過select標簽的 fetchType來覆蓋-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<typeAliases>
<typeAlias alias="emp" type="com.pyn.entity.Employee" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 單獨使用時配置成MANAGED沒有事務(wù) -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis/EmployeeMapper.xml"/>
</mappers>
</configuration>
測試類
String resource = "mybatis-config.xml";
InputStream in = null;
SqlSessionFactory factory = null;
SqlSession session = null;
try{
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
in = Resources.getResourceAsStream(resource);
factory = builder.build(in);
session = factory.openSession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
List<Employee> emps = mapper.searchEmps();
for(int i = 0;i<emps.size();i++){
System.out.print(emps.get(i));
}
}catch(IOException e){
}finally {
session.close();
}
2.3、Mybatis執(zhí)行原理

1、SqlSessionFactoryBuilder去讀取mybatis全局配置文件,然后build一個DefaultSqlSessionFactory;
2、當(dāng)我們獲取到SqlSessionFactory之后,就可以通過SqlSessionFactory去獲取SqlSession對象;
3、通過MapperProxy動態(tài)代理咱們的dao,執(zhí)行接口里面的方法的時候,其實是對應(yīng)的mapperProxy在代理;
4、通過代理對象執(zhí)行CURD操作;
3、Mybatis主要開發(fā)元素
實際上,在mybatis開發(fā)中,涉及到主要開發(fā)要素是:dao接口類,mapper映射文件,以及po實體類。它們之間的關(guān)系如下:

dao接口類中,定義了數(shù)據(jù)庫操作的增刪改查接口方法;po類定義接口方法的參數(shù),可使用po類保存查詢結(jié)果,或者為insert,update方法提供數(shù)據(jù)集參數(shù)。操作數(shù)據(jù)庫表的SQL語句保存在mapper映射文件中。
3.1、mapper映射文件

在mapper映射文件中,主要包含如下配置元素:
mapper元素。該元素是最頂層的配置元素,其屬性namespace指向接口全類型名,在mapper元素下面,包含如下子元素:resultMap元素,select元素,insert元素,update元素,delete元素。
3.1.1、resultMap元素
使用resultMap配置節(jié),建立po類的數(shù)據(jù)字段與查詢結(jié)果集的列名之間的映射關(guān)系。當(dāng)po類的數(shù)據(jù)字段與查詢結(jié)果集的列名不一致的時候,使用resultMap建立兩者之間的映射關(guān)系。注意:resultMap與resultType不可同時存在,后者主要用于簡單查詢并且查詢結(jié)果集與po類的數(shù)據(jù)字段一致。
<resultMap type="emp" id="myEmp1">
<id property="eId" column="eid" />
<result property="eName" column="ename" />
<result property="eInDate" column="eindate" />
<result property="eSalary" column="esalary" />
<result property="dId" column="did" />
</resultMap>
1、type屬性執(zhí)行po類的全類型名,即:包名+類名。如果在mybatis配置文件中,為po類建立了別名,可以引用該別名。
2、id屬性應(yīng)該全局唯一,它被select元素的resultMap屬性引用。
3、<id>子元素用來建立po數(shù)據(jù)字段與查詢結(jié)果集主鍵列之間的映射關(guān)系。
4、<result>子元素用來建立po數(shù)據(jù)字段與查詢結(jié)果集非主鍵列之間的映射關(guān)系。
5、property屬性用來指定po類的數(shù)據(jù)字段名。
6、column屬性用來指定數(shù)據(jù)庫表的列名。
3.1.2、select元素
在mapper文件中,使用select元素來管理select語句。
<select id="searchEmps" resultMap="myEmp1">
select * from employee
</select>
1、id屬性就是對應(yīng)執(zhí)行查詢方法的方法名;
2、resultMap建立結(jié)果集列和po屬性的關(guān)聯(lián) 與resultType不可共存,后者查詢結(jié)果集與po屬性相同;
3、parameterType屬性,傳遞參數(shù)的類型;
注意:
resultType屬性的值可以是如下情形:
1.基本數(shù)據(jù)類型,如:int,String等;
2.class數(shù)據(jù)類型,如:java bean,這里輸入的是全類型名或者別名;
3.map數(shù)據(jù)類型。包括:單對象和集合兩種;
4.集合數(shù)據(jù)類型,是集合元素的類型,而非集合本身;
3.1.3、insert/update/delete元素
上述三種分別對應(yīng)添加、修改、刪除功能。功能類似。
添加
<insert id="insertEmp" parameterType="emp">
insert into employee(ename,eindate,esalary,did)
values(#{eName},#{eInDate},#{eSalary},#{dId})
</insert>
刪除
<delete id="deleteEmp" parameterType="int">
delete from employee where eid = #{eId}
</delete>
修改
<update id="updateEmp" parameterType="emp">
update employee set ename = #{eName},eindate = #{eInDate},
esalary = #{eSalary},did = #{dId}
where eid = #{eId}
</update>
3.1.4、小結(jié)
在mapper映射文件中,當(dāng)然不僅僅只有上述幾個元素,當(dāng)然還有其他的元素,上述四個元素對應(yīng)數(shù)據(jù)庫操作的查詢、添加、修改、刪除。
注意:
1、映射文件的Namespace必須等于接口的全路徑名稱;
2、映射文件的sql唯一標示id必須等于接口方法的名稱;
3、映射文件的parameterType必須等于接口方法的參數(shù)類型;
4、映射文件的resultType/resultMap必須等于接口方法的返回類型;
3.2、全局配置文件
mybatis-config.xml文件(當(dāng)然名字可以修改)全局配置文件,主要包含以下元素,從上往下依次為(注意順序不可亂):
3.2.1、properties屬性
properties屬性主要用來加載/修改屬性properties配置文件,例如:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
全局配置文件引入
<!--引入數(shù)據(jù)庫配置文件-->
<properties resource="db.properties"></properties>
3.2.2、settings屬性
mybatis框架運行時可以調(diào)整一些運行參數(shù)。比如,開啟二級緩存,開啟延遲加載等等。全局參數(shù)會影響mybatis的運行行為。比較常用的有以下幾個:
cacheEnabled:在全局范圍內(nèi)啟用或禁用緩存配置 任何映射器在此配置下,默認True;
lazyLoadingEnabled:在全局范圍內(nèi)啟用或禁用延遲加載。禁用時,所有相關(guān)聯(lián)的將熱加載。默認True;
logImpl:指定MyBatis的日志實現(xiàn)使用。如果此設(shè)置是不存在的記錄的實施將自動查找。默認not set;
aggressiveLazyLoading:啟用時,有延遲加載屬性的對象將被完全加載后調(diào)用懶惰的任何屬性。否則,每一個屬性是按需加載。默認True;
<settings>
<!-- 打印查詢語句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 控制全局緩存(二級緩存)-->
<setting name="cacheEnabled" value="true"/>
<!-- 延遲加載的全局開關(guān)。當(dāng)開啟時,所有關(guān)聯(lián)對象都會延遲加載。默認 false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 當(dāng)開啟時,任何方法的調(diào)用都會加載該對象的所有屬性。默認 false,可通過select標簽的 fetchType來覆蓋-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
3.2.3、typeAliases屬性
typeAliases元素用于為配置文件中的Java類型設(shè)置一個簡短的名字,即設(shè)置別名。別名的設(shè)置與XML配置相關(guān),其使用的意義在于減少全限定類名的冗余。
//1. 使用<typeAliases>元素配置別名的方法如下:
<typeAliases>
<typeAlias alias="emp" type="com.pyn.entity.Employee"/>
</typeAliases>
//2. 當(dāng)POJO類過多時,可以通過自動掃描包的形式自定義別名,別名默認為類名首字母小寫具體如下:
<typeAliases>
<package name="com.pyn.entity"/>
</typeAliases>
//3.在2的前提下,可以通過注解@Alias()重新起個別名
@Data
@Alias("employee")
public class Employee {
private Integer eId;
private String eName;
private Date eInDate;
private Double eSalary;
private Integer dId;
}
3.2.4、typeHandler屬性
typeHandler的作用就是將預(yù)處理語句中傳入的參數(shù)從javaType(Java類型)轉(zhuǎn)換為jdbcType(JDBC類型),或者從數(shù)據(jù)庫取出結(jié)果時將jdbcType轉(zhuǎn)換為javaType。
//1.注冊一個類的類型處理器
<typeHandlers>
<typeHandler handler="com.pyn.type.EmployeetypeHandler" />
</typeHandlers>
//2.注冊一個包中所有的類型處理器
<typeHandlers>
<package name="com.pyn.type" />
</typeHandlers>
3.2.5、objectFactoty屬性
objectFactoty元素,MyBatis中默認的ObjectFactory的作用是實例化目標類,它既可以通過默認構(gòu)造方法實例化,也可以在參數(shù)映射存在的時候通過參數(shù)構(gòu)造方法來實例化。通常使用默認的ObjectFactory即可。
3.2.6、plugins屬性
plugins元素,用來配置插件,MyBatis允許在已映射語句執(zhí)行過程中的某一點進行攔截調(diào)用,這種攔截調(diào)用是通過插件來實現(xiàn)的。<plugins>元素的作用就是配置用戶所開發(fā)的插件。
3.2.7、environments屬性
environments元素用于對環(huán)境進行配置。MyBatis的環(huán)境配置實際上就是數(shù)據(jù)源的配置,我們可以通過<environments>元素配置多種數(shù)據(jù)源,即配置多種數(shù)據(jù)庫。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 單獨使用時配置成MANAGED沒有事務(wù) -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--
environments:mybatis可以配置多種環(huán)境 ,default指定使用某種環(huán)境。
environment:配置一個具體的環(huán)境信息;必須有兩個標簽;id代表當(dāng)前環(huán)境的唯一標識
transactionManager:事務(wù)管理器;
type:事務(wù)管理器的類型;JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory)
自定義事務(wù)管理器:實現(xiàn)TransactionFactory接口.type指定為全類名
dataSource:數(shù)據(jù)源;
type:數(shù)據(jù)源類型:
1、POOLED:表示支持JDBC數(shù)據(jù)源連接池。這樣可避免每次請求都要創(chuàng)建新的連接;
2、UNPOOLED:表示不支持數(shù)據(jù)源連接池。這樣每次請求都會進行打開和關(guān)閉數(shù)據(jù)庫連接操作;
3、JNDI:表示支持外部數(shù)據(jù)源連接池。比如JNDI;
4、自定義數(shù)據(jù)源:實現(xiàn)DataSourceFactory接口,type是全類名;
-->
3.2.8、databaseIdProvider屬性
databaseIdProvider多數(shù)據(jù)庫支持,mybatis可以根據(jù)不同的數(shù)據(jù)庫廠商執(zhí)行不同的語句,基于映射語句中的databaseId屬性。
<databaseIdProvider type="DB_VENDOR">
<!-- 為不同的數(shù)據(jù)庫廠商起別名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
#在映射文件中,執(zhí)行對應(yīng)操作的時候 加入標識databaseId
<select id="getEmpById" resultType="emp"
databaseId="mysql">
select * from employee where eid = #{eid}
</select>
3.2.9、mapper屬性
mapper元素作用是指定MyBatis映射文件的位置。
# 1 單個加載映射文件
<mappers>
<mapper resource="mybatis/EmployeeMapper.xml"/>
</mappers>
# 2 加載接口 注意接口名要和映射文件名保持一致
<mappers>
<mapper class="com.pyn.mapper.EmployeeMapper"/>
</mappers>
# 3 批量加載 mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中
<mappers>
<mapper class="com.pyn.mapper"/>
</mappers>