大致思路

感觉好多事物都遵循28原则,mybatis也不例外,2成的代码能够完成8成的需求。我就准备分析一下主要的代码。以下是大纲(待定)

JDBC和mybatis

mybatis是基于jdbc的。jdbc提供了java客户端与关系型数据库的一套标准接口。能够完成连接数据库、提交sql语句等基本功能。那mybatis又主要做了哪些事情呢?

  1. 能够选择使用连接池,复用数据库连接。
  2. 能够通过注解或xml来管理sql语句。
  3. 能够将结果集映射为java bean。
  4. 缓存、懒加载、插件扩展等。

再来对比并复习下jdbc和mybatis的demo吧。

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。
以下均为基本思路,后面各个章节会细讲。
数据库连接管理我们只考虑连接池,基本思路:数据库连接后,将其放在一个list中。每次获取SQLSession,list中有则取出来,若list中没有并且未超过连接池最大连接数则获取新的连接,否则等待。每次关闭SQLSession,则将连接放回list中。

sql语句管理我们只考虑注解的方式。因为xml最终还是会转化为java对象。通过demo中可以看到,我们是将sql定义在了接口的方法注解上。我们可以通过反射来获取到注解上sql语句,以及选项。这时我们就知道这个方法该如何执行sql语句了,就可以用动态代理生成这个方法了。

结果集映射结果集映射,首先我们要获取方法的返回类型,因此最重要的还是反射。如果还考虑懒加载的话,那就要用到动态代理了。

02-11 22:20