咱們的工具和各類框架的做用就是爲了咱們操做數據庫簡潔,對於一些數據庫的工具能幫咱們少寫一些處理異常等等的代碼,可是他們並非自動化的,不少的操做仍是須要咱們本身進行,因此咱們的框架就幫咱們把中間黑色的部分封裝起來了,減小咱們的負擔,可是SQL也是重中之重,咱們須要把這些東西本身來控制就有 MyBatis 這個半自動框架,以及咱們須要學習更多的關於 HQL 的內容。<!--more-->java
相對於Hibernate 他的優勢就是能夠進行SQL 的定製化,能讓咱們的SQL更加優化,雖然 Hibernate 也能夠這麼作可是有一點就是咱們須要在原來的框架的基礎上學習更多的 HQL 相關的東西,加劇學習負擔。mysql
首先咱們須要創建一個新的工程,第一步就是進入 MyBatis 的依賴,固然也少不了數據庫的依賴,這裏咱們爲了方便實體類的編寫咱們還加上了 Lombok ,以及log4j :spring
<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>
須要在類路徑下編寫配置文件:sql
<?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>
<?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> <!--過濾器設置輸出的級別--> <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" /><!-- 設置日誌輸出文件名 --> <!-- 設置是否在從新啓動服務時,在原有日誌的基礎添加新日誌 --> <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的設置,additivity指示是否遵循缺省的繼承機制--> <logger name="com.runway.bssp.activeXdemo" additivity="false"> <appender-ref ref="activexAppender" /> </logger> <!-- 根logger的設置--> <root> <priority value ="debug"/> <appender-ref ref="myConsole"/> <appender-ref ref="myFile"/> </root> </log4j:configuration>
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; }
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標識 2.綁定的參數 Object employee = sqlSession.selectOne("selectOneEmployee", 3); System.out.println(employee); }finally { if (sqlSession != null) { sqlSession.close(); } } } }
<?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和測試類裏的參數必須是須要匹配的才行。好比咱們的 id 就是咱們的測試類中的 select 方法須要傳的參數,而後咱們的 resultType 就是一個實體類的具體路徑。數據庫
上面咱們使用的方式是之前比較老的方式,如今再也不使用那種方式了,咱們如今都是面向的接口編程的,因此咱們使用Mapper 類來完成數據庫訪問。apache
建立一個mapper接口,而後裏面寫方法便可:編程
package lwen.dao; import lwen.entries.Employee; public interface EmployeeMapper { public Employee getEmployeeById(Integer id); }
能夠看到就是這麼簡單,可是咱們一開始是經過方法的參數和咱們的 xml 的查詢語句連接起來的,這裏咱們又怎麼作這個映射關係呢?其實就是須要在咱們的 xml 中配置咱們的 這個Mapper 的路徑,以及咱們的方法做爲查詢語句的 id 屬性,還有返回值類型,等等。接下來就來看這些配置。安全
接下來就是配置咱們的 mapper 的xml了,讓他和咱們的接口掛鉤。session
<?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>
注意事項:mybatis
@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); //直接調用的 mapper 裏的方法 System.out.println(employeeMapper.getEmployeeById(3)); }finally { if (sqlSession != null) { sqlSession.close(); } } }
這裏咱們會發現咱們根本沒有寫接口的實現類,咱們怎麼獲取到咱們的 Mapper 的對象,而且還能夠調用他的方法呢?實際上咱們去打印一下咱們使用sqlSession.getMapper(EmployeeMapper.class)
這句話獲取到咱們的對象,而且能執行相應的操做呢?
咱們打印出來這個對象咱們就會發現,獲取到的對象其實是一個代理對象,那麼也就是說咱們 Mybatis 底層採用的代理方式作的具體的功能。
其實咱們經過SqlSession.getMapper(XXXMapper.class) 方法,MyBatis 會根據相應的接口聲明的方法信息,經過動態代理機制生成一個Mapper 實例,咱們使用Mapper 接口的某一個方法時,MyBatis 會根據這個方法的方法名和參數類型,肯定Statement Id,底層仍是經過SqlSession.select("statementId",parameterObject);
或者SqlSession.update("statementId",parameterObject);
等等來實現對數據庫的操做,(至於這裏的動態機制是怎樣實現的,我想專門用一篇文章來討論)
MyBatis 引用 Mapper 接口這種調用方式,純粹是爲了知足面向接口編程的須要。(其實還有一個緣由是在於,面向接口的編程,使得用戶在接口上可使用註解來配置SQL語句,這樣就能夠脫離XML配置文件,實現「0配置」)。 由於面向接口編程其實有很是多的好處。由於如今咱們的 dao 代碼就是咱們的 mapper 接口了,可是若是有一天咱們但願不採用 MyBatis 來作數據訪問了,咱們在底層就能夠直接寫對應的實現類使用 Hibernate 等等其餘框架來頂替,也是一件很容易的事。
編輯於 2018-06-01