大致思路
感觉好多事物都遵循28原则,mybatis也不例外,2成的代码能够完成8成的需求。我就准备分析一下主要的代码。以下是大纲(待定)
JDBC和mybatis
mybatis是基于jdbc的。jdbc提供了java客户端与关系型数据库的一套标准接口。能够完成连接数据库、提交sql语句等基本功能。那mybatis又主要做了哪些事情呢?
- 能够选择使用连接池,复用数据库连接。
- 能够通过注解或xml来管理sql语句。
- 能够将结果集映射为java bean。
- 缓存、懒加载、插件扩展等。
再来对比并复习下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语句了,就可以用动态代理生成这个方法了。
结果集映射结果集映射,首先我们要获取方法的返回类型,因此最重要的还是反射。如果还考虑懒加载的话,那就要用到动态代理了。