淺析mybatis源碼(一)整體思路

大體思路

感受好多事物都遵循28原則,Mybatis也不例外,2成的代碼可以完成8成的需求。我就準備分析一下主要的代碼。如下是大綱(待定)java

JDBC和mybatis

mybatis是基於jdbc的。jdbc提供了java客戶端與關係型數據庫的一套標準接口。可以完成鏈接數據庫、提交sql語句等基本功能。那mybatis又主要作了哪些事情呢?mysql

  1. 可以選擇使用鏈接池,複用數據庫鏈接。
  2. 可以經過註解或xml來管理sql語句。
  3. 可以將結果集映射爲java bean。
  4. 緩存、懶加載、插件擴展等。

再來對比並複習下jdbc和mybatis的demo吧。sql

import java.sql.*;

public class HelloWorld {
    static final String user = "";
    static final String password = "";
    static final String url = "";
    public static void main(String[] args) throws Throwable{
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection(url,user, password);
        Statement statement = connection.prepareStatement("select * from product where id = ?");
        ((PreparedStatement) statement).setInt(1, 1);
        ResultSet resultSet = ((PreparedStatement) statement).executeQuery();
        while (resultSet.next()){
            String name = resultSet.getString("name");
            double price = resultSet.getDouble("price");
            String imgUrl = resultSet.getString("img_url");
            System.out.println("name: "+name+" price: "+price+" imgUrl: "+imgUrl);
        }

    }
}

以上是jdbc的demo。能夠看到很是的簡單粗暴。加載相應的數據庫驅動後,就能經過url、帳號、密碼來獲取鏈接了。再經過Statement來構造sql語句。結果存儲在ResultSet中。具體能夠查看jdbc的文檔。
接下來看下mybatis的demo數據庫

//Product實體類
import lombok.Data;

@Data
public class Product {
    private long id;
    private String name;
    private String imgUrl;
    private double price;
}
//Product Mapper
public interface ProductMapper {
    @Select("select * from product where id = #{id}")
    Product detail(long id);
}
//DataSource工廠類
public class DataSourceFactory {
  public static DataSource getDataSource() {
    String driver = "com.mysql.jdbc.Driver";
    String url = "";
    String username = "";
    String password = "";
    return new PooledDataSource(driver, url, username, password);
  }
}
//Environment工廠類
public class EnvironmentFactory {
  static Environment getEnvironment(){
    return new Environment("dev", new JdbcTransactionFactory(), DataSourceFactory.getDataSource());
  }
}
//SQLSession工具類
public class SqlSessionFactoryUtil {
  private static SqlSessionFactory sqlSessionFactory = null;
  private static Object lock = new Object();
  private static void addMapper(Configuration configuration){
    configuration.addMapper(ProductMapper.class);
  }
  public static void initSqlSessionFactory() {
    sqlSessionFactory = null;
    Environment environment = EnvironmentFactory.getEnvironment();
    Configuration configuration = new Configuration(environment);
    addMapper(configuration);
    synchronized (lock){
      if(sqlSessionFactory == null){
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
      }
    }
  }
  public static SqlSession getSqlSession() {
    if(sqlSessionFactory == null){
      initSqlSessionFactory();
    }
    return sqlSessionFactory.openSession();
  }
}

代碼可能比較多。可是仔細看,其實都是很簡單的代碼。Product實體類和ProductMapper就不說了。DataSourceFactory就是設置了下帳號密碼等用來鏈接數據庫,使用的類主要是PooledDataSource,使用鏈接池方式鏈接數據庫。EnvironmentFactory就是設置了下數據源是剛剛的DataSource,使用jdbc管理事務。SQLSession工具類就是經過SqlSessionFactoryBuilder來獲取sqlSessionFactory,再獲取SqlSession。接下來看下如何使用吧。緩存

public class TestOrderMapper {
    private SqlSession sqlSession = null;
    private ProductMapper productMapper= null;
    @Before
    public void init(){
        sqlSession = SqlSessionFactoryUtil.getSqlSession();
        productMapper = sqlSession.getMapper(ProductMapper.class);
    }
    @Test
    public void getProduct(){
        Product product = productMapper.detail(1);
        System.out.println(product);
    }
    @After
    public void close() {
        sqlSession.close();
    }
}
demo對比

經過這兩段代碼的對比。咱們可以看到mybatis的主要優勢是:
1.管理了數據庫鏈接。能夠看到咱們操做的並非數據庫鏈接,而是SQLSession。
2.經過註解管理sql語句。
3.將結果集映射到sql語句。
是否是和上面作的比較對應上了。mybatis

如何實現mybatis

接來下該進入主題了,如何實現mybatis。
如下均爲基本思路,後面各個章節會細講。
數據庫鏈接管理咱們只考慮鏈接池,基本思路:數據庫鏈接後,將其放在一個list中。每次獲取SQLSession,list中有則取出來,若list中沒有而且未超過鏈接池最大鏈接數則獲取新的鏈接,不然等待。每次關閉SQLSession,則將鏈接放回list中。app

sql語句管理咱們只考慮註解的方式。由於xml最終仍是會轉化爲java對象。經過demo中能夠看到,咱們是將sql定義在了接口的方法註解上。咱們能夠經過反射來獲取到註解上sql語句,以及選項。這時咱們就知道這個方法該如何執行sql語句了,就能夠用動態代理生成這個方法了。工具

結果集映射結果集映射,首先咱們要獲取方法的返回類型,所以最重要的仍是反射。若是還考慮懶加載的話,那就要用到動態代理了。ui

相關文章
相關標籤/搜索