在介绍MyBatis的核心组件之前,我们首先了解一下如何使用MyBatis框架完成数据库的增删改查操作。为了便于演示,我们需要通过create-table.sql和init-data.sql脚本中的SQL语句新建一张User表并往表中初始化一些数据。
create-table.sql文件中创建表的语句如下:
drop table user if exists;
create table user (
id int generated by default as identity,
create_time varchar(20) ,
name varchar(20),
password varchar(36),
phone varchar(20),
nick_name varchar(20),
primary key (id)
);
init-data.sql文件中初始化数据SQL的内容如下:
insert into user (create_time, name, password, phone, nick_name) values('2010-10-23 10:20:30', 'User1', 'test', '18700001111', 'User1');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-24 10:20:30', 'User2', 'test', '18700001111', 'User2');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-25 10:20:30', 'User3', 'test', '18700001111', 'User3');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User4', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User5', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User6', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User7', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User8', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User9', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User10', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User11', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User12', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User13', 'test', '18700001111', 'User4');
insert into user (create_time, name, password, phone, nick_name) values('2010-10-26 10:20:30', 'User14', 'test', '18700001111', 'User4');
使用MyBatis框架操作数据库,大致需要以下几步:
(1)编写MyBatis的主配置文件MyBatis使用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>
<settings>
<setting name="useGeneratedKeys" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="LOG4J"/>
</settings>
<environments default="dev" >
<environment id="dev">
<transactionManager type="JDBC">
<property name="" value="" />
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:mybatis" />
<property name="username" value="sa" />
<property name="password" value="" />
</dataSource>
</environment>
<environment id="qa">
<transactionManager type="JDBC">
<property name="" value="" />
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:mybatis_qa" />
<property name="username" value="admin" />
<property name="password" value="admin" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/blog4java/mybatis/example/mappers/UserMapper.xml"/>
<!--
<mapper resource="file:///mybatis/com/blog4java/mybatis/example/mapper/UserMapper.xml"/>
<mapper class="com.blog4java.mybatis.com.blog4java.mybatis.example.mapper.UserMapper"/>
<package name="com.blog4java.mybatis.com.blog4java.mybatis.example.mapper"/>
-->
</mappers>
</configuration>
MyBatis主配置文件可以配置MyBatis框架的参数信息,这些参数会改变 MyBatis的运行时行为。例如上面的配置中,useGeneratedKeys参数表示支持返回自动生成主键,当然这个特性需要JDBC驱动程序兼容。如果参数值设置为true,则进行INSERT操作后,数据库自动生成的主键会填充到Java实体属性中,尽管一些驱动不能兼容,但仍可正常工作。其他参数的含义会在后面中详细介绍。
在上面的配置中,<environment>标签用于配置环境信息,包括事务管理器、数据源等信息。我们可以根据开发环境、测试环境、生产环境等配置不同的数据源信息,然后通过<environments>标签的default属性指定当前激活的环境。
<mappers>标签用于指定Mapper文件的位置。
除此之外,MyBatis主配置文件中还可以注册类型别名,自定义的TypeHandler、Plugin,等等。MyBatis主配置文件的更多细节会在后面中详细介绍,这里就不展开了。
2)新增Java实体与数据库记录建立映射
MyBatis属于半自动化的ORM框架,能够将数据库中的记录转换为Java实体,因此我们需要编写一个Java实体类与数据库中的表相对应,代码如下:
@Data
public class UserEntity {
private Long id;
private String name;
private Date createTime;
private String password;
private String phone;
private String nickName;
}
(3)定义用于执行SQL的Mapper
MyBatis的Mapper配置包括两部分,首先需要定义Mapper接口,然后通过XML或Java注解方式配置SQL语句。这里笔者定义了一个UserMapper接口,代码如下:
package com.blog4java.mybatis.example.mapper;
import com.blog4java.mybatis.example.entity.UserEntity;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserMapper {
List<UserEntity> listAllUser();
@Select("select * from user where id=#{userId,jdbcType=INTEGER}")
UserEntity getUserById(@Param("userId") String userId);
List<UserEntity> getUserByEntity( UserEntity user);
UserEntity getUserByPhone(@Param("phone") String phone);
}
Mapper接口定义完毕后,需要通过XML或者Java注解方式配置SQL语句,代码如下:
<?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.blog4java.mybatis.example.mapper.UserMapper">
<sql id="userAllField">
id,create_time, name, password, phone, nick_name
</sql>
<select id="listAllUser" resultType="com.blog4java.mybatis.example.entity.UserEntity" >
select
<include refid="userAllField"/>
from user
</select>
<select id="getUserByEntity" resultType="com.blog4java.mybatis.example.entity.UserEntity">
select
<include refid="userAllField"/>
from user
<where>
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND name = #{name}
</if>
<if test="phone != null">
AND phone = #{phone}
</if>
</where>
</select>
<select id="getUserByPhone" resultType="com.blog4java.mybatis.example.entity.UserEntity">
select
<include refid="userAllField"/>
from user
where phone = ${phone}
</select>
</mapper>
(4)通过MyBatis提供的API执行我们定义的Mapper
@Test
public void testMybatis () throws IOException {
// 获取配置文件输入流
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 通过SqlSessionFactoryBuilder的build()方法创建SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 调用openSession()方法创建SqlSession实例
SqlSession sqlSession = sqlSessionFactory.openSession();
// 获取UserMapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行Mapper方法,获取执行结果
List<UserEntity> userList = userMapper.listAllUser();
// // 兼容Ibatis,通过Mapper Id执行SQL操作
// List<UserEntity> userList = sqlSession.selectList(
// "com.blog4java.mybatis.example.mapper.UserMapper.listAllUser");
System.out.println(JSON.toJSONString(userList));
}
如上面的代码所示,SqlSession是MyBatis中提供的与数据库交互的接口,SqlSession实例通过工厂模式创建。为了创建SqlSession对象,首先需要创建SqlSessionFactory对象,而SqlSessionFactory对象的创建依赖于SqlSessionFactoryBuilder类,该类提供了一系列重载的build()方法,我们需要以主配置文件的输入流作为参数调用SqlSessionFactoryBuilder对象的bulid()方法,该方法返回一个SqlSessionFactory对象。有了SqlSessionFactory对象之后,调用SqlSessionFactory对象的openSession()方法即可获取一个与数据库建立连接的SqlSession实例。前面我们定义了UserMapper接口,这里需要调用SqlSession的getMapper()方法创建一个动态代理对象,然后调用UserMapper代理实例的方法即可完成与数据库的交互。
需要注意的是,MyBatis来源于iBatis项目,所以依然保留了iBatis执行Mapper的方式,代码如下:
List<UserEntity> userList = sqlSession.selectList(
"com.blog4java.mybatis.example.mapper.UserMapper.listAllUser");
MyBatis中还提供了一个SqlSessionManager类,我们同样可以使用SqlSessionManager对象完成与数据库的交互,代码如下:
@Test
public void testSessionManager() throws IOException {
Reader mybatisConfig = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionManager sqlSessionManager = SqlSessionManager.newInstance(mybatisConfig);
sqlSessionManager.startManagedSession();
UserMapper userMapper = sqlSessionManager.getMapper(UserMapper.class);
List<UserEntity> userList = userMapper.listAllUser();
System.out.println(JSON.toJSONString(userList));
}
如上面的代码所示,SqlSessionManager使用了单例模式,在整个应用程序中只存在一个实例,我们可以通过该类提供的静态方法newInstance获取SqlSessionManager类的实例。SqlSessionManager实现了SqlSessionFactory和SqlSession接口,既可以获取SqlSession实例,又可以替代SqlSession完成与数据库的交互。