一、MyBatis 介绍
MyBatis 是一个优秀的基于 Java 的持久层框架(是一个DAO层的框架),它内部封装了 JDBC,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
MyBatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 Java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句。最后 MyBatis 框架执行 sql 并将结果映射为 Java 对象并返回。
MyBatis 的过去: MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code ,并且改名为MyBatis。2013年11月迁移到Github。
名字由来:iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)。
当前,最新版本是MyBatis 3.5.9,其发布时间是2021年12月26日。
优点: 采用 ORM 思想解决了实体和数据库映射的问题,对 JDBC 进行了封装,屏蔽了 JDBC API 底层访问细节,使我们不用与 JDBC API 打交道,就可以完成对数据库的持久化操作。
二、入门 MyBatis
前面的介绍我们提到了DAO层、JDBC、sql语句本身、映射等。下面来简单说说使用 MyBatis 的六大步骤:
① 添加 MyBatis 的坐标
② 创建 user 数据表
③ 编写 User 实体类
④ 编写映射文件 UserMapper.xml
⑤ 编写核心配置文件 SqlMapConfig.xml
⑥ 编写 DAO 层,使用动态代理实现
第①步中的“坐标”就相当于是在引入jar包,假设我们是用 Maven 进行的开发,那么可以在 pox.xml 文件中写你需要的 MyBatis 依赖,示例如下:
<dependencies>
……
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
……
</dependencies>
第②、③步创建数据表和实体类不用多说。
第④步提到了映射文件:UserMapper.xml,该文件的名字一般由实体类+Mapper 组成,文件里面是sql语句,相当于 DAO 层接口的实现类。但这个文件的存放位置有点讲究,它在resource目录下的某个包里,这个包名必须跟实体类的包名同步,举例说明,实体类 User.java 放在 com.***.domain 下,那么映射文件 UserMapper.xml 的包名得是 com.***.mapper 。映射文件中的sql语句的参数不再用? 做占位符了,写法变为 #{实体类属性名} 。
第⑤步是编写核心配置文件:SqlMapConfig.xml,里面是数据库连接的四要素、事务管理器等。它直接放在resource目录下即可。
第⑥步编写DAO层接口,并使用动态代理的方式编写测试类,有四个点需要注意:1、映射文件中的namespace与接口类的全限定名相同;2、接口类中的方法名要和映射文件中定义的每个sql的id值相同;3、接口类中的方法的输入参数类型要和映射文件中定义的每个sql的parameterType的类型相同;4、接口类中的方法的输出参数类型要和mapper.xml中定义的每个sql的resultType的类型相同。
三、源码示例
源码只举例第④、⑥步的代码,其他几步就不多说了!
第④步 核心配置文件 SqlMapConfig.xml ,代码如下:
<?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>
<properties resource="jdbc.properties"></properties>
<typeAliases>
<typeAlias type="com.***.domain.User" alias="user"></typeAlias>
</typeAliases>
<environments default="developement">
<environment id="developement">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/***/mapper/UserMapper.xml"/>
</mappers>
</configuration>
jdbc.properties 源码:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/你的数据库名
jdbc.username=登录名
jdbc.password=登录密码
第一站:查
编写映射文件 UserMapper.xml (映射文件相当于DAO层接口的实现类):
<?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">
<mapper namespace="com.***.dao.UserMapper">
<select id="findAll" resultType="user">
select * from User
</select>
<select id="findById" resultType="user" parameterType="int">
select * from user where id=#{id}
</select>
</mapper>
如果使用动态代理实现,那么 DAO 层的接口类 UserMapper.java 源码如下:
package com.***.dao;
import com.***.domain.User;
import java.io.IOException;
import java.util.List;
public interface UserMapper {
public List<User> findAll() throws IOException;
public User findById(int id);
}
编写测试类,使用代理开发方式调用 DAO 层:
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> all = mapper.findAll();
System.out.println(all);
User user = mapper.findById(1);
System.out.println(user);
sqlSession.close();
第二站:增
编写映射文件 UserMapper.xml :
<mapper namespace="com.***.dao.UserMapper">
<insert id="add" parameterType="user">
insert into user values(#{id},#{username},#{password})
</insert>
</mapper>
DAO 层接口类 UserMapper.java 的源码增加内容如下:
public void add(User user);
编写测试类,使用代理开发方式调用 DAO 层:
User user = new User();
user.setId(2);
user.setUsername("lucy");
user.setPassword("1234");
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.add();
sqlSession.commit();
sqlSession.close();
第三站:删
编写映射文件 UserMapper.xml :
<mapper namespace="com.***.dao.UserMapper">
<delete id="delete" parameterType="int">
delete from user where id=#{id}
</delete>
</mapper>
DAO 层接口类 UserMapper.java 的源码增加内容如下:
public void delete(int id);
编写测试类,使用代理开发方式调用 DAO 层:
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.delete(2);
sqlSession.commit();
sqlSession.close();
第四站:改
编写映射文件 UserMapper.xml :
<mapper namespace="com.***.dao.UserMapper">
<update id="update" parameterType="user">
update user set username=#{username},password=#{password} where id=#{id}
</update>
</mapper>
DAO 层接口类 UserMapper.java 的源码增加内容如下:
public void update(User user);
编写测试类,使用代理开发方式调用 DAO 层:
User user = new User();
user.setId(2);
user.setUsername("kang");
user.setPassword("kang");
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.update(user);
sqlSession.commit();
sqlSession.close();
四、更多使用说明
映射文件
映射文件如 UserMapper.xml 中各部分代码说明:
优化映射文件:使用动态sql语句
动态sql语句的实现常用 <if> 判断或者 <foreach> 循环标签。用 <if> 实现不同条件下的查询,UserMapper.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">
<mapper namespace="com.***.dao.UserMapper">
<select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=0">
and id=#{id}
</if>
<if test="username!=null">
and username=#{username}
</if>
<if test="password!=null">
and password=#{password}
</if>
</where>
</select>
</mapper>
用 <foreach> 实现同一条件下多种情况的查询,UserMapper.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">
<mapper namespace="com.***.dao.UserMapper">
<select id="findByIds" parameterType="list" resultType="user">
select * from user
<where>
<foreach collection="list" open="id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>
<foreach> 标签用于遍历集合,它的属性含义如下:
核心配置文件
文件中使用的所有标签如下图所示。标签在文件中的先后就是图片上的顺序(如 mapper 不能放在 environments 标签之前)。
常用标签 | 说明 |
---|
properties 属性 | 实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件(如jdbc.properties文件),该标签可以加载额外配置的properties文件。
| typeAliases 类型别名 |
| environments 环境 | 其中,事务管理器(transactionManager)类型有两种: - JDBC,这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。 - MANAGED,这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
数据源(dataSource)类型有三种: - UNPOOLED,这个数据源的实现只是每次被请求时打开和关闭连接。 - POOLED,这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。 - JNDI,这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
| mapper 映射器 | 该标签的作用是加载映射的。加载方式有四种,常用第一种。 1. 使用相对于类路径的资源引用,例如?<mapper resource="org/mybatis/builder/AuthorMapper.xml"/> 2. 使用完全限定资源定位符(URL),例如?<mapper url="file:///var/mappers/AuthorMapper.xml"/> 3. 使用映射器接口实现类的完全限定类名,例如?<mapper class="org.mybatis.builder.AuthorMapper"/> 4. 将包内的映射器接口实现全部注册为映射器,例如?<package name="org.mybatis.builder"/>
|
相应API方法
- SqlSessionFactoryBuilder 工厂构建器
方法 SqlSessionFactory build(InputStream inputStream) 通过加载 MyBatis 的核心配置文件的输入流的形式构建一个SqlSessionFactory对象。
举例:
String resource = "org/mybatis/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
其中,Resources 这个工具类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个 WEB URL 中加载资源文件。
- SqlSessionFactory 工厂对象
SqlSessionFactory 有多个个方法创建SqlSession 实例。常用的有如下两个:
创建实例 | 说明 |
---|
openSession() | 会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提交该事务,更新操作数据才会持久化到数据库中。 | openSession(boolean autoCommit) | 参数为是否自动提交,如果设置为true,那么不需要手动提交事务。 |
- SqlSession 会话对象
SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。
执行语句的方法主要有: |
---|
T selectOne(String statement, Object parameter) | List selectList(String statement, Object parameter) | int insert(String statement, Object parameter) | int update(String statement, Object parameter) | int delete(String statement, Object parameter) |
操作事务的方法主要有: |
---|
void commit() | void rollback() |
|