MyBatis 初探

MyBatis 是一个开源持久化框架,用于简化Java开发中的数据库访问。它支持customer SQL, stored proceduresdifferent types of mapping relations。该框架也是一种交互式框架,先期准备好交互的必要条件,然后构建一个交互环境,在交互环境中划分出会话,每次会话也有一个交互环境。当环境准备好了之后,就可以交换数据来(涉及到网络通信,一般都是这种处理方式)。

主要完成两件事:

  • 通过JDBC完成与数据库的连接
  • 通过反射完成Java对象和数据库参数之间的映射关系

通过SQLMap文件获得statement语句,同时形成ParameterMap和ResultMap两个对象,用于处理参数和SQL对象,这样加上数据库连接,就可以执行SQL语句了。

运行原理(iBatis)

  • SqlMapSession->SessionScode->Establish Connection->RequestScope
  • execute SQL
    • 映射Java对象参数到ParameterMap
    • 映射数据库列到ResultMap
  • RequestScope归还到对象池-释放Connection-归还SessionScope-销毁SqlMapSession

Java APIs

  • SqlMapClientImpl
    • ExtendedSqlMapClient
      • SqlMapClient: 定义客户端的CRUD
        • SqlMapExecutor
        • SqlMapTransactionManager
    • SqlMapSessionImpl
      • SqlMapSession: 提供客户端在当前线程的执行环境
        • SqlMapExecutor
        • SqlMapTransactionManager
  • SqlMapExecutorDelegate: 工具类,耦合了操作和执行环境

Statement相关的类

  • DeleteStatement
  • InsertStatement
  • SelectStatement
  • UpdateStatement
    • GeneralStatement
    • BaseStatement
      • MappedStatement
      • ResultMap
      • Sql
      • ParameterMap

SQLSessionFactory

SQLSessionFactory是MyBatis应用的核心,使用对应的Builder和配置文件来实例化。配置文件中包含了如下信息:

  • data source definition
  • transaction manager details
  • mappers of relations between entities

SQLSession

SQLSession 使用SQLSessionFactory(非线程安全)来实例化,。包含了如下操作:

  • performing database operations
  • obtaining mappers
  • managing transactions

SqlSession实现了AutoCloseableinterface,可以使用如下形式:

1
2
3
try(SqlSession session = sqlSessionFactory.openSession()) {
// do work
}

Maven 依赖

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>

Mappers

  • CRUD注解:调用被注解的方法,执行对应的SQL
    • @Insert
    • @Select
    • @Update
    • @Delete
  • @Results 设置查询结果与Java类的映射关系
    • @Result
  • @Many
    • @One
  • @MapKey
  • @Options 定义全局的开关和配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface PersonMapper {

@Insert("Insert into person(name) values (#{name})")
public Integer save(Person person);

// ...

@Select(
"Select personId, name from Person where personId=#{personId}")
@Results(value = {
@Result(property = "personId", column = "personId"),
@Result(property="name", column = "name"),
@Result(property = "addresses", javaType = List.class,
column = "personId", many=@Many(select = "getAddresses"))
})
public Person getPersonById(Integer personId);

@Insert("Insert into address (streetAddress, personId
values(#{streetAddress}, #{personId})")
@Options(useGeneratedKeys = false, flushCache=true)
public Integer saveAddress(Address address);
// ...
}

Dynamic SQL

动态生成SQL语句,相对于传统JDBC易于调试,不易出错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//SQL使用
@SelectProvider(type=MyBatisUtil.class, method="getPersonByName")
public Person getPersonByName(String name);

public class MyBatisUtil {

// SQL定义

public String getPersonByName(String name){
return new SQL() {{
SELECT("*");
FROM("person");
WHERE("name like #{name} || '%'");
}}.toString();
}
}

存储过程的调用

结论

参考资料