一. Mybatis的基本概念
Mybatis的前身是Apache开源项目iBatis,2010更名为Mybatis并由github托管。Mybatis是一个java持久层框架技术,它通过对jdbc的简单封装,实现了程序与SQL语句的分离,使得开发者从繁杂的样板代码中解放出来,可以专注于业务逻辑的实现。Mybatis使用了基于接口的动态代理技术,使得数据访问层DAO(@Repository)不需要实现类就可以运行,只需要一个dao接口和xml映射文件即可。与Hibernate相同的是,它们都使用了某种方式使得应用中的domain类和数据库中的表之间建立映射关系,从而可以实现应用中的实体类和表中的记录之间的自动封装(只要domain对象属性和数据库表中字段名称相同即可)。与Hibernate不同的是,mybatis不屏蔽SQL,对于性能要求极高或者需求经常变动的互联网项目而言非常重要(SQL语句优化)。
二. Mybatis中的核心组件
1. SqlSessionFactoryBuilder & SqlSessionFactory
SqlSessionFactoryBuilder是一个构造器,他会根据mybatis的核心配置文件(mybatis-config.xml)创建SqlSessionFactory对象,SqlSessionFactoryBuilder的生命周期为创建SqlSessionFactory对象的方法。SqlSessionFactory是一个工厂接口,mybatis中的默认实现类是DefaultSqlSessionFactory,它的作用是创建mybatis的核心接口SqlSession的实现类,用于操作数据库。SqlSessionFactory的生命周期和应用程序一样,应该采用单例模式。
2. SqlSession
SqlSession是mybatis的核心接口,默认实现类是DefaultSqlSession(单线程中使用),作用相当于jdbc中的Connection数据库连接对象。SqlSession有三个作用:
- 获取Mapper接口的代理对象(在基于接口的代理开发模式中使用)
- 直接发送SQL语句操作数据库(iBatis中遗留的方法)
- 控制数据库事务,相当于在jdbc中使用try…catch…finally手动控制事务(与spring整合之后交由spring管理事务)
3. 映射器
映射器是mybatis中最重要也最复杂的组件,映射由一个DAO层接口和一个xml映射文件组成,作用如下:
- 描述映射关系(建立domain属性和表字段的映射关系,详见ResultMap)
- 提供SQL语句,SQL查询参数的类型、返回值类型(用于自动映射)…
- 动态SQL语句的配置
映射器的主要作用就是将SQL语句的查询结果映射为domain对象的属性,或者将domain对象的数据插入到SQL语句中的参数中(CRUD)。
三. Mybatis的基础demo
-
domain对象
public class Role { private Long id; private String roleName; private String note; // getter & setter ...
-
创建映射器接口:RoleMapper.java
public interface RoleMapper { int insertRole(Role role); int deleteRole(Long id); int updateRole(Role role); Role getRoleById(Long id); // 根据用户名模糊查询用户列表 List<Role> findRoles(String roleName); }
-
创建xml映射文件:RoleMapper.xml(非常重要),后面有详细的笔记
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace元素: 用于指定mapper接口的路径,关联mapper接口 --> <mapper namespace="com.znker.repository.RoleMapper"> <!-- id元素值和Mapper接口中的方法名称必须一致,这样调用Mapper接口中的方法时mybatis 才知道发送哪一条SQL语句 parameterType元素表示SQL语句的入参,可以是基本类型、String、pojo...没有使用 别名的时候要使用pojo的全路径 --> <insert id="insertRole" parameterType="com.znker.domain.Role"> insert into t_role(role_name, note) values(#{roleName}, #{note}) </insert> <delete id="deleteRole" parameterType="long"> delete from t_role where id = #{id} </delete> <delete id="updateRole" parameterType="com.znker.domain.Role"> update t_role set role_name = #{roleName}, note = #{note} where id = #{id} </delete> <select id="getRoleById" parameterType="long" resultType="com.znker.domain.Role"> select id, role_name as roleName, note from t_role where id = #{id} </select> <select id="findRoles" parameterType="string" resultType="com.znker.domain.Role"> select id, role_name as roleName, note from t_role where role_name like concat('%', #{roleName}, '%') </select> </mapper>
-
mybatis的核心配置文件:mybatis-config.xml,这个配置文件内容将影响mybatis的运行方式,例如可以在此配置mybatis的分页插件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置数据源,可以配置多个环境(开发、测试、生产...)与spring整合之后交由spring配置 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments> <!-- 加载domain的映射文件,可以依次加载,也可以使用文件扫描批量加载 --> <mappers> <mapper resource="mapper/RoleMapper.xml" /> </mappers> </configuration>
-
SqlSessionFactory的工具类,使用单例模式创建SqlSessionFactory对象:
public class SqlSessionFactoryUtils { private final static Class<SqlSessionFactoryUtils> LOCK = SqlSessionFactoryUtils.class; private static SqlSessionFactory sqlSessionFactory = null; // 构造方法 private SqlSessionFactoryUtils(){ } public static SqlSessionFactory getSqlSessionFactory(){ // 防止在多线程环境中多次实例化SqlSessionFactory对象 synchronized (LOCK){ if (sqlSessionFactory != null){ return sqlSessionFactory; } InputStream inputStream; try { // 加载mybatis核心配置文件,创建SqlSessionFactory对象 inputStream = Resources.getResourceAsStream("mybatis/mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e){ e.printStackTrace(); return null; } return sqlSessionFactory; } } public static SqlSession openSqlSession(){ if (sqlSessionFactory == null){ getSqlSessionFactory(); } return sqlSessionFactory.openSession(); } }
-
测试demo
public class RoleTest { private SqlSessionFactory sqlSessionFactory = null; @Before public void beforeTest(){ sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); } @Test public void testGetRole(){ SqlSession sqlSession = sqlSessionFactory.openSession(); try { // 使用SqlSession对象获取Mapper接口对象,调用接口中定义的方法,发送SQL操作数据库 RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Role role = roleMapper.getRoleById(101L); System.out.println(role); } finally { if (sqlSession != null){ sqlSession.close(); } } } @Test public void testFindRoles(){ SqlSession sqlSession = sqlSessionFactory.openSession(); try { RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); List<Role> list = roleMapper.findRoles("znker"); System.out.println(list); } finally { if (sqlSession != null){ sqlSession.close(); } } } }
四. Mybatis的核心配置文件
mybatis的配置文件中有很多配置项可以使用,会影响mybatis的运行,大部分时候使用默认值就可以,无需手动配置。其中使用比较多的配置项有:别名设置、插件配置、mapper映射文件的加载
-
别名Alias:当应用中的类全限定名称很长的时候,如果要多次引用会不方便,此时可以使用别名。mybatis的别名分为系统别名和自定义别名。系统别名:java基本类型、String、Collection(list / map / hashmap)、date…这些类型的别名mybatis中已经注册好了,可以直接使用。自定义别名需要自己注册到mybatis中才能使用,例如应用中的domain,两种在mybatis-config.xml中注册别名的方法
<!-- 依次手动注册别名 --> <typeAliases> <typeAlias alias="type" type="com.znker.domain.Role" /> <typeAlias alias="user" type="com.znker.domain.User" /> </typeAliases> <!-- 使用包扫描批量注册别名 --> <typeAliases> <package name="com.znker.domain" /> </typeAliases>
-
引入映射器,在配置文件加载所有映射文件:
<!-- 手动加载所有映射文件 --> <mappers> <mapper resource="com/znker/repository/RoleMapper.xml" /> <mapper resource="com/znker/repository/UserMapper.xml" /> </mappers> <!-- 使用包扫描机制批量加载有所映射文件 --> <mappers> <package name="com.znker.repository" /> </mappers>