在介紹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完成與資料庫的互動。