MyBatis筆記一:GettingStart
1.MyBatis優(yōu)點
我們的工具和各種框架的作用就是為了我們操作數(shù)據(jù)庫簡潔凹耙,對于一些數(shù)據(jù)庫的工具能幫我們少寫一些處理異常等等的代碼滞诺,但是他們并不是自動化的藏澳,很多的操作還是需要我們自己進行,所以我們的框架就幫我們把中間黑色的部分封裝起來了删豺,減少我們的負擔(dān)遭贸,但是SQL也是重中之重掖疮,我們需要把這些東西自己來控制就有 MyBatis 這個半自動框架,以及我們需要學(xué)習(xí)更多的關(guān)于 HQL 的內(nèi)容扎瓶。
相對于Hibernate 他的優(yōu)點就是可以進行SQL 的定制化所踊,能讓我們的SQL更加優(yōu)化,雖然 Hibernate 也可以這么做但是有一點就是我們需要在原來的框架的基礎(chǔ)上學(xué)習(xí)更多的 HQL 相關(guān)的東西栗弟,加重學(xué)習(xí)負擔(dān)污筷。
2.Getting Start
1.引入依賴
首先我們需要建立一個新的工程,第一步就是進入 MyBatis 的依賴乍赫,當(dāng)然也少不了數(shù)據(jù)庫的依賴瓣蛀,這里我們?yōu)榱朔奖銓嶓w類的編寫我們還加上了 Lombok ,以及l(fā)og4j :
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
2.編寫配置文件
需要在類路徑下編寫配置文件:
<?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 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:///spring_data"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
</configuration>
2.log4j配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<appender name="myConsole" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n" />
</layout>
<!--過濾器設(shè)置輸出的級別-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="debug" />
<param name="levelMax" value="warn" />
<param name="AcceptOnMatch" value="true" />
</filter>
</appender>
<appender name="myFile" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="D:/output.log" /><!-- 設(shè)置日志輸出文件名 -->
<!-- 設(shè)置是否在重新啟動服務(wù)時雷厂,在原有日志的基礎(chǔ)添加新日志 -->
<param name="Append" value="true" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
</layout>
</appender>
<appender name="activexAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="E:/activex.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="[%d{MMdd HH:mm:ss SSS\} %-5p] [%t] %c{3\} - %m%n" />
</layout>
</appender>
<!-- 指定logger的設(shè)置惋增,additivity指示是否遵循缺省的繼承機制-->
<logger name="com.runway.bssp.activeXdemo" additivity="false">
<appender-ref ref="activexAppender" />
</logger>
<!-- 根logger的設(shè)置-->
<root>
<priority value ="debug"/>
<appender-ref ref="myConsole"/>
<appender-ref ref="myFile"/>
</root>
</log4j:configuration>
3.編寫實體類
package lwen.entries;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Employee {
private int id;
private String name;
private int age;
}
4.編寫測試類
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;
public class GettingStart {
@Test
public void sessionFactoryTest() throws IOException {
String resource = "mybatis.xml";
InputStream stream = Resources.getResourceAsStream(resource);
SqlSession sqlSession = null;
try {
//獲取sql工廠
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(stream);
//獲取sql session
sqlSession = sessionFactory.openSession();
// 1.sql標(biāo)識 2.綁定的參數(shù)
Object employee = sqlSession.selectOne("selectOneEmployee", 3);
System.out.println(employee);
}finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
5.編寫mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC " -//mybatis.org//DTD Mapper 3.e//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectOneEmployee" resultType="lwen.entries.Employee">
select * from employee where id=#{id}
</select>
</mapper>
注意這里其實我們的mapper和測試類里的參數(shù)必須是需要匹配的才行。比如我們的 id 就是我們的測試類中的 select 方法需要傳的參數(shù)改鲫,然后我們的 resultType 就是一個實體類的具體路徑诈皿。
6.總結(jié)基本套路
根據(jù)xml配置文件(全局配置文件)創(chuàng)建一個Sq1SessionFactory對象,xml是用來配置數(shù)據(jù)源一些運行環(huán)境信息
sql映射文件:配置了每一個sql像棘,以及sql的封裝規(guī)則等稽亏。
將sq1映射文件注冊在全局配置文件中
-
寫Java代碼:
1)、根據(jù)全局置文件得到Sq1SessionFactory缕题;
2)截歉、使用sqlSession工廠,獲取到sqlSession對象使用他來執(zhí)行增改查烟零,一個sqlSession就是代表和數(shù)據(jù)庫的一次會話瘪松,用完關(guān)閉
3)咸作、使用sql的唯一標(biāo)志來告訴MyBatis執(zhí)行哪個sql,語句都是保存在Sql映射文件中的宵睦。
上面我們使用的方式是以前比較老的方式记罚,現(xiàn)在不再使用那種方式了,我們現(xiàn)在都是面向的接口編程的壳嚎,所以我們使用Mapper 類來完成數(shù)據(jù)庫訪問桐智。
3.面向接口編程
1.編寫接口Mapper
創(chuàng)建一個mapper接口,然后里面寫方法即可:
package lwen.dao;
import lwen.entries.Employee;
public interface EmployeeMapper {
public Employee getEmployeeById(Integer id);
}
可以看到就是這么簡單诬辈,但是我們一開始是通過方法的參數(shù)和我們的 xml 的查詢語句鏈接起來的酵使,這里我們又怎么做這個映射關(guān)系呢?其實就是需要在我們的 xml 中配置我們的 這個Mapper 的路徑焙糟,以及我們的方法作為查詢語句的 id 屬性口渔,還有返回值類型,等等穿撮。接下來就來看這些配置缺脉。
2.配置Mapper.xml
接下來就是配置我們的 mapper 的xml了,讓他和我們的接口掛鉤悦穿。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC " -//mybatis.org//DTD Mapper 3.e//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="lwen.dao.EmployeeMapper">
<select id="getEmployeeById" resultType="lwen.entries.Employee">
select * from employee where id=#{id}
</select>
</mapper>
注意事項:
- 第一點就是我們的 namespace 以前事隨便寫攻礼,但是這個地方就是需要我們和Mapper 接口綁定,也就是我們的接口的全類名栗柒。
- 然后就是我們的id屬性礁扮,就是我們的Mapper的方法名。
- 還有一點疑問就是我們的參數(shù)瞬沦,我們都沒傳太伊,其實這里他做了默認綁定,參數(shù)名和這里的sql模板參數(shù)名一致就行逛钻。
3.測試類
@Test
public void InterfaceMapperTest() throws IOException {
String resource = "mybatis.xml";
InputStream stream = Resources.getResourceAsStream(resource);
SqlSession sqlSession = null;
try {
//獲取sql工廠
SqlSessionFactory sessionFactory = getSessionFactory("mybatis.xml");
//獲取sql session
sqlSession = sessionFactory.openSession();
// 獲取 mapper 接口的實例對象
EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
//直接調(diào)用的 mapper 里的方法
System.out.println(employeeMapper.getEmployeeById(3));
}finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
4.一個神奇的點
這里我們會發(fā)現(xiàn)我們根本沒有寫接口的實現(xiàn)類僚焦,我們怎么獲取到我們的 Mapper 的對象,并且還可以調(diào)用他的方法呢曙痘?實際上我們?nèi)ゴ蛴∫幌挛覀兪褂?sqlSession.getMapper(EmployeeMapper.class)
這句話獲取到我們的對象芳悲,并且能執(zhí)行相應(yīng)的操作呢?
我們打印出來這個對象我們就會發(fā)現(xiàn)边坤,獲取到的對象實際上是一個代理對象名扛,那么也就是說我們 Mybatis 底層采用的代理方式做的具體的功能。
其實我們通過SqlSession.getMapper(XXXMapper.class) 方法茧痒,MyBatis 會根據(jù)相應(yīng)的接口聲明的方法信息肮韧,通過動態(tài)代理機制生成一個Mapper 實例,我們使用Mapper 接口的某一個方法時,MyBatis 會根據(jù)這個方法的方法名和參數(shù)類型惹苗,確定Statement Id,底層還是通過SqlSession.select("statementId",parameterObject);
或者SqlSession.update("statementId",parameterObject);
等等來實現(xiàn)對數(shù)據(jù)庫的操作耸峭,(至于這里的動態(tài)機制是怎樣實現(xiàn)的桩蓉,我想專門用一篇文章來討論)
MyBatis 引用 Mapper 接口這種調(diào)用方式,純粹是為了滿足面向接口編程的需要劳闹。(其實還有一個原因是在于院究,面向接口的編程,使得用戶在接口上可以使用注解來配置SQL語句本涕,這樣就可以脫離XML配置文件业汰,實現(xiàn)“0配置”)。 因為面向接口編程其實有非常多的好處菩颖。因為現(xiàn)在我們的 dao 代碼就是我們的 mapper 接口了样漆,但是如果有一天我們希望不采用 MyBatis 來做數(shù)據(jù)訪問了,我們在底層就可以直接寫對應(yīng)的實現(xiàn)類使用 Hibernate 等等其他框架來頂替晦闰,也是一件很容易的事放祟。
4.總結(jié)
- SqlSession代表和數(shù)據(jù)庫的一次會話:用完必須關(guān)閉,這也是一個資源呻右,所以我們用完了必須進行關(guān)閉操作跪妥,避免數(shù)據(jù)庫不必要的問題。
- SqlSession和connection一樣都是非線程安全声滥,每次使用都應(yīng)該去獲取新的對象眉撵,不可以當(dāng)作一個成員變量 ,不然自然會導(dǎo)致紊亂落塑,也就是我們需要把他放在一個局部方法中纽疟,用完關(guān)閉。其實說清楚點他的底層就是 connection芜赌。
- mapper接口沒有實現(xiàn)類仰挣,但是mybatis會為這個接口生成一個代理對象。(將接口和xml進行綁定)
- 兩個重要的配置文件:
- mybatis的全局配置文件:包含數(shù)據(jù)庫連接池信息缠沈,事務(wù)管理器信息等膘壶。。洲愤。系統(tǒng)運行環(huán)境信息
- sql映射文件:保存了每一個sq1語句的映射信息:將sql抽取出來颓芭。