說明java
MyBatis版本:3.5.1sql
相關歷史文章(閱讀本文以前,您可能須要先看下以前的系列)數據庫
Spring Boot MyBatis最全教程:你值得擁有MyBatis能脫離Spring嗎 一圖縱覽MyBatis的工做原理
說明java
MyBatis版本:3.5.1sql
相關歷史文章(閱讀本文以前,您可能須要先看下以前的系列)數據庫
Spring Boot MyBatis最全教程:你值得擁有手寫MyBatis,純手工打造開源框架(第一篇:風雲再起)數組
手寫MyBatis,純手工打造開源框架(第二篇:君臨天下) session
前言mybatis
經過上面咱們已經能夠構建了SqlSessionFactory,接下來的話就是要怎麼獲取一個SqlSession。app
1、分析框架
對於SqlSession的構建的話,須要有一個屬性Configuration,這個屬性在上面的SqlSessionFactory已經有了;另外對於SqlSession的真正的Sql執行是交給了Executor,Executor是真正和數據庫進行交互了,因此須要將數據庫配置信息傳給Executor。工具
2、編碼測試
2.1 Executor
構造SqlSession須要有Executor,咱們先建立一個Executor接口:
package com.kfit.mybatis.session; import java.util.List; import com.kfit.mybatis.config.MapperStatement; public interface Executor { <E> List<E> query(MapperStatement ms, Object parameter); }
咱們實現一個最基本的SimpleExecutor:
package com.kfit.mybatis.session.impl; import java.util.List; import com.kfit.mybatis.config.JdbcProperties; import com.kfit.mybatis.config.MapperStatement; import com.kfit.mybatis.session.Executor; public class SimpleExecutor implements Executor { private JdbcProperties jdbcProperties; public SimpleExecutor(JdbcProperties jdbcProperties) { this.jdbcProperties = jdbcProperties; } public <E> List<E> query(MapperStatement ms, Object parameter) { //具體的方法待實現 return null; } }
說明:
(1)這裏咱們實現了最基本的Simple,在MyBatis有3種狀況須要處理,咱們實現最簡單的方式。
(2)這裏咱們接收了jdbcproperties爲了以後直接進行數據庫的鏈接操做,在mybatis數據庫的鏈接關閉,提交,回滾是有一個事務類Transaction。
2.2 SqlSessionFactory
在SqlSessionFactory中添加一個獲取SqlSession的方法:
public interface SqlSessionFactory { public Configuration getConfiguration(); public SqlSession openSession(); }
在DefaultSqlSessionFactory實現openSession()方法:
public SqlSession openSession() { Executor executor = new SimpleExecutor(configuration.getJdbcProperties()); SqlSession sqlSession = new DefaultSqlSession(configuration, executor); return sqlSession; }
2.3 SimpleExecutor數據庫操做
咱們這個對數據庫操做的核心代碼:
package com.kfit.mybatis.session.impl; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.kfit.mybatis.config.JdbcProperties; import com.kfit.mybatis.config.MapperStatement; import com.kfit.mybatis.session.Executor; public class SimpleExecutor implements Executor { private JdbcProperties jdbcProperties; public SimpleExecutor(JdbcProperties jdbcProperties) { this.jdbcProperties = jdbcProperties; } public <E> List<E> query(MapperStatement ms, Object parameter) { List<E> ret = new ArrayList<E>(); // 具體的方法待實現 try { // 加載驅動 Class.forName(jdbcProperties.getDriver()); } catch (ClassNotFoundException e) { e.printStackTrace(); } Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // 獲取鏈接 connection = DriverManager.getConnection(jdbcProperties.getUrl(), jdbcProperties.getUsername(), jdbcProperties.getPassword()); // 預編譯sql語句 preparedStatement = connection.prepareStatement(ms.getSql()); // 處理sql語句中的佔位符 parameterize(preparedStatement, parameter); // 執行sql語句 resultSet = preparedStatement.executeQuery(); // 處理結果 handlerResultSet(resultSet, ret, ms.getResultType()); } catch (SQLException e) { e.printStackTrace(); } return ret; } private void parameterize(PreparedStatement preparedStatement, Object parameter) throws SQLException { if (parameter instanceof String) { preparedStatement.setString(1, (String) parameter); } else if (parameter instanceof Long) { preparedStatement.setLong(1, (Long) parameter); } else if (parameter instanceof Integer) { preparedStatement.setInt(1, (Integer) parameter); } } private <E> void handlerResultSet(ResultSet resultSet, List<E> ret, String className) { Class<E> clazz = null; try { clazz = (Class<E>) Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { while (resultSet.next()) { // 經過反射實例化對象 Object entity = clazz.newInstance(); // 使用反射工具將resultSet中的數據填充到entity中 // id,name,sex,age // 獲取實體類的全部屬性,返回Field數組 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String fname = field.getName(); Type type = field.getGenericType(); if (type.toString().equals("class java.lang.String")) { String column = resultSet.getString(fname); field.set(entity, column); }else if (type.toString().equals("long")) { Long column = resultSet.getLong(fname); field.set(entity, column); } } ret.add((E) entity); } } catch (SQLException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
說明:
(1)在MyBatis中這個代碼是分好幾個類進行處理的,這裏爲了講解方便,統一放在一個類中。
(2)數據庫的鏈接操做:這裏使用jdbc鏈接數據庫獲取到connection進行操做。
(3)使用泛型處理返回的結果(handlerResultSet)。
2.4 SqlSession的方法
到這裏,咱們就能夠編寫SqlSession的方法了,這裏定義兩個方法SelectOne和SelectList();
public interface SqlSession { <T> T selectOne(String statement, Object parameter); <E> List<E> selectList(String statement); <E> List<E> selectList(String statement, Object parameter); }
對應的DefaultSqlSession:
package com.kfit.mybatis.session.impl; import java.util.List; import com.kfit.mybatis.config.Configuration; import com.kfit.mybatis.session.Executor; import com.kfit.mybatis.session.SqlSession; public class DefaultSqlSession implements SqlSession { private Configuration configuration; private Executor executor; public DefaultSqlSession(Configuration configuration,Executor executor) { this.configuration= configuration; this.executor = executor; } public <E> List<E> selectList(String statement) { return executor.query(configuration.getMapperStatement(statement),null); } public <E> List<E> selectList(String statement,Object parameter) { return executor.query(configuration.getMapperStatement(statement), parameter); } public <T> T selectOne(String statement,Object parameter) { List<T> list = executor.query(configuration.getMapperStatement(statement),parameter); if(list.size()>0) { return list.get(0); } return null; } }
說明:DefaultSqlSession的具體處理交給了Executor,因此這裏的具體的實現就比較簡單了。
2.5 測試下
在main方法來進行測試一下吧:
public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = App.class.getClassLoader().getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); System.out.println(sqlSessionFactory); System.out.println(sqlSessionFactory.getConfiguration().getJdbcProperties().getUrl()); SqlSession sqlSession = sqlSessionFactory.openSession(); Demo demo = null; List<Demo> demos = null; //使用sqlSession直接查詢 demo = sqlSession.selectOne("com.kfit.mybatis.demo.mapper.DemoMapper.getById",1L); System.out.println(demo); demos = sqlSession.selectList("com.kfit.mybatis.demo.mapper.DemoMapper.getAll"); System.out.println(demos); }
這個方法和以前寫mybatis的使用方式上是如出一轍的,運行看下效果吧:
Demo[id=1, name=張三1]
[Demo [id=1, name=張三1], Demo [id=9, name=張三], Demo [id=10, name=張三], Demo [id=11, name=張三], Demo [id=12, name=張三], Demo [id=13, name=張三]]
看到如此帥氣的結果,這是爽歪歪,厲害了個人哥。本篇就先介紹到這裏,下一篇咱們將會介紹無敵的Mapper實現。
我就是我,是顏色不同的煙火。
我就是我,是不同凡響的小蘋果。
à悟空學院:http://t.cn/Rg3fKJD
學院中有Spring Boot相關的課程!點擊「閱讀原文」進行查看!
SpringBoot視頻:http://t.cn/R3QepWG
Spring Cloud視頻:http://t.cn/R3QeRZc
SpringBoot Shiro視頻:http://t.cn/R3QDMbh
SpringBoot交流平臺:http://t.cn/R3QDhU0
SpringData和JPA視頻:http://t.cn/R1pSojf
SpringSecurity5.0視頻:http://t.cn/EwlLjHh
Sharding-JDBC分庫分表實戰:http://t.cn/E4lpD6e