再版
著者: Yebo
バージョン: v1.0
元のアドレス
第 1 章 mybatis の概要
1.1 マイバチの歴史
- Mybatis は、2010 年以前は ibatis と呼ばれていました。Apache 内のプロジェクトです。名前は、インターネット + ibatis から来ています。Java ベースの永続層フレームワークです。
- 2010 年以降、Apache から Google Code に移行され、mybatis に名前が変更されました。
- 2013年にgithubに移行
1.2 マイバティスとは
- 優れた永続層フレームワークです
- カスタマイズされた SQL、ストアド プロシージャ、高度なマッピングをサポート
- ほとんどすべての JDBC コードでパラメータを手動で設定し、結果セットを取得することを回避できます。
- ネイティブ情報は、単純な XML または注釈を使用して構成およびマッピングできます。
- インターフェースを使用して、Java POJO (Plain Old Java Object、通常の Java オブジェクト) をデータベース内のレコードにマップします。
1.3 mybatisの利点
- JDBC と比較して、侵入的ではなく、良好なデカップリング効果を実現できます。
- Hibernate と比較してパフォーマンスが高く、現在のモバイル インターネット時代のほとんどのニーズを満たすことができます。
- SQL コード分類は、メンテナンスを容易にするためにさまざまな SQL マップに配置されます。
1.4 Mybatisコアファイルの書き込み
- POJOマッピングデータベーステーブルJavaオブジェクト
- データベースを操作するためのデータ アクセス オブジェクト (DAOS) マッパー インターフェイス クラス
- SQL マップ : DAO インターフェイスを登録するために使用される SQL マッピング構成ファイル。これにより、インターフェイスがデータベースを操作できるようになります。
- mybatis 構成ファイル、SqlSessionFactory を生成するためのいくつかの基本的な構成情報を初期化します。
第 2 章 はじめに HelloWorld
- データベーステーブルの作成
//创建数据库
CREATE DATABASE mybatis DEFAULT CHARACTER SET UTF8;
//创建数据库表
CREATE TABLE user(
`user_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`user_name` VARCHAR(100) NOT NULL COMMENT '用户名',
`create_time` DATETIME DEFAULT NULL comment '创建时间'
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8 COMMENT="用户表";
- HelloWorld コードの作成を開始する
①プロジェクトを作成し、jarパッケージ
mybatis-3.4.6.jar
mysql-connector-java-5.1.7-bin.jarを追加
②公式サイトの手順に従い、段階的に環境を構築
③junitテストを使用してテストインターフェース
- ステップ
ステップ 1 データベーステーブルをマップするエンティティクラスを作成する
public class User {
//用户ID
private Integer userId;
//用户名
private String userName;
//创建时间
private Date createTime;
public User() {
}
public User(Integer userId, String userName, Date createTime) {
this.userId = userId;
this.userName = userName;
this.createTime = createTime;
}
}
ステップ 2 データベース テーブルを操作するためのインターフェイス クラスを作成する
public interface UserMapper {
/*
* 添加用户
*/
void addUser(User user);
/*
* 删除用户
*/
void deleteUser(Integer userId);
/*
* 更新用户
*/
void updateUser(User user);
/*
* 通过用户ID获取用户信息
*/
User getUser(Integer userId);
/*
* 获取用户列表
*/
List<User> getUsers();
/*
* 根据名字模糊查询获取用户列表
*/
List<User> getUsersLikeByUserName(@Param("userName") String userName);
}
ステップ3 データベースインターフェースクラスを登録・操作するためのマッピングファイルを作成します
データベースの操作はSQL文のみですが、mybatisではデータベースを操作するためのインターフェースを提供しています 一般的にインターフェースにはデータベースを操作する機能はありませんが、ただし、mybatis はこの構成ファイルを通じてインターフェースを登録できるため、インターフェースはデータベースを操作できるようになります。
<?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.im.mapper.UserMapper">
<!--
此配置文件用来注册UserMapper这个接口以及此接口中定义的方法
namespace: 被注册接口的全类名
insert: 插入数据的标签,还有其他三个标签 查询select、更新update、删除delete
id: 接口里面定义的方法名字
parameterType: 方法的入参类型(全类名)
#{xxx}: 表达式 : 取方法的参数值
如果方法的入参是基本数据类型那么xxx为形参名
如果方法的入参为对象类型那么xxx为对象类型里面的属性名
resultType:方法的返回值类型
useGeneratedKeys: 让 myabtis 框架使用JDBC 通过 getGeneratedKeys 获取数据库主键.
keyProperty: 映射通过getGeneratedKeys获取的键值
-->
<insert id="addUser" parameterType="com.im.entity.User" useGeneratedKeys="true" keyProperty="userId">
INSERT INTO user(user_name,create_time) VALUES(#{userName},#{createTime})
</insert>
<delete id="deleteUser" parameterType="Integer">
DELETE FROM user WHERE user_id=#{userId}
</delete>
<update id="updateUser" parameterType="com.im.entity.User">
UPDATE user SET user_name=#{userName},create_time=#{createTime} WHERE user_id=#{userId}
</update>
<select id="getUser" parameterType="Integer" resultType="com.im.entity.User">
SELECT user_id as userId,user_name as userName,create_time as createTime FROM user WHERE user_id=#{userId}
</select>
<select id="getUsers" resultType="com.im.entity.User">
SELECT user_id as userId,user_name as userName,create_time as createTime FROM user
</select>
<!--
构建LIKE参数
方式一: CONCAT('参数1','参数2','参数3')
方式二: 在传参数时构建成 %李雷%
方式三: 使用bind标签创建元素,放到上下文中
-->
<select id="getUsersLikeByUserName" resultType="com.sc.entity.User">
SELECT user_id as userId,user_name as userName,create_time as createTime FROM user WHERE user_name like CONCAT('%',#{userName},'%')
</select>
<select id="getUsersLikeByUserName" resultType="com.sc.entity.User">
SELECT user_id as userId,user_name as userName,create_time as createTime FROM user WHERE user_name like #{userName}
</select>
<select id="getUsersLikeByUserName" resultType="com.sc.entity.User">
<bind name="pattern" value="'%' + _parameter.userName + '%'" />
SELECT user_id as userId,user_name as userName,create_time as createTime FROM user WHERE user_name like #{pattern}
</select>
</mapper>
ステップ 4 mybatis コア オブジェクトを生成するための mybatis コア設定ファイル mybatis-config.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!-- 数据库驱动 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- mysql数据库地址 -->
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
<!-- 数据库用户名 -->
<property name="username" value="root"/>
<!-- 数据库密码 -->
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 将注册接口的配置文件注册到mybatis的核心配置文件中,这是jar包版本,如果是maven项目,要放在resources文件夹下 -->
<mapper resource="com/im/mapper/UserMapper.xml"/>
</mappers>
</configuration>
ステップ 5 単体テスト クラスを介してインターフェイス テストを呼び出します (mybatis ネイティブ API バージョンの呼び出し)
public class UserMapperTest1 {
/*
* 添加用户
*/
@Test
public void testAddUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//创建statement
String statement = "com.im.mapper.UserMapper.addUser";
//构建入参
User user = new User();
user.setUserName("Tom");
user.setCreateTime(new Date());
int row = session.insert(statement, user);
System.out.println("row:"+row);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 删除用户
*/
@Test
public void testDeleteUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//创建statement
String statement = "com.im.mapper.UserMapper.deleteUser";
//调用mybatis的删除数据的API
int row = session.delete(statement, 1);
System.out.println("row:"+row);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 更新用户
*/
@Test
public void testUpdateUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//创建statement
String statement = "com.im.mapper.UserMapper.updateUser";
//调用mybatis的更新数据的API
//构建更新入参
User user = new User(2, "polly", new Date());
int row = session.update(statement, user);
System.out.println("row:"+row);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 根据ID获取用户
*/
@Test
public void testGetUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//创建statement
String statement = "com.im.mapper.UserMapper.getUser";
//调用mybatis的查询单个数据的API
User user = session.selectOne(statement, 2);
System.out.println("user:"+user);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 获取用户列表
*/
@Test
public void testGetUsers() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//创建statement
String statement = "com.im.mapper.UserMapper.getUsers";
//调用mybatis的查询列表数据的API
List<User> list = session.selectList(statement);
System.out.println("users:"+list);
//提交
session.commit();
//关闭会话
session.close();
}
}
ステップ 6 単体テスト クラスを介してインターフェイス テストを呼び出します (mybatis マッパー バージョンの呼び出し)
public class UserMapperTest2 {
/*
* 添加用户
*/
@Test
public void testAddUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构建入参
User user = new User();
user.setUserName("张三");
user.setCreateTime(new Date());
//调用添加用户方法
userMapper.addUser(user);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 删除用户
*/
@Test
public void testDeleteUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//调用删除方法
userMapper.deleteUser(2);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 更新用户
*/
@Test
public void testUpdateUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构建更新入参
User user = new User(2, "polly", new Date());
//调用更新方法
userMapper.updateUser(user);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 根据ID获取用户
*/
@Test
public void testGetUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//调用查询方法
User user = userMapper.getUser(3);
System.out.println("user:"+user);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 获取用户列表
*/
@Test
public void testGetUsers() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//调用查询全部方法
List<User> users = userMapper.getUsers();
System.out.println("users:"+users);
//提交
session.commit();
//关闭会话
session.close();
}
}
第3章 mybatis共通属性の設定
- プロパティ: 外部プロパティ リソース ファイルをインポートして、データベース構成情報を Java コードに書き込む際の問題を解決します。
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!-- 数据库驱动 -->
<property name="driver" value="${jdbc_driver}" />
<!-- mysql数据库地址 -->
<property name="url" value="${jdbc_url}" />
<!-- 数据库用户名 -->
<property name="username" value="${user}" />
<!-- 数据库密码 -->
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
- typeAliases: エイリアスの問題を解決する
在mybatis-config.xml配置文件中配置别名
<!-- 别名设置 -->
<typeAliases>
<!-- 将全类名 com.im.entity.User 映射成别名 user -->
<!-- 单个设置 -->
<!-- <typeAlias type="com.im.entity.User" alias="user"/> -->
<!-- 多个设置,将放在com.im.entity包下的所有Javabean都设置别名 -->
<package name="com.im.entity"/>
</typeAliases>
- 設定: mybatis のいくつかの一般的な構成
在mybatis-config.xml配置文件中配置一些mybatis的基本属性
<settings>
<!-- 二级缓存开启 默认开启 -->
<setting name="cacheEnabled" value="true"/>
<!-- 懒加载 默认值 false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 即时加载 默认是false (true in ≤3.4.1)在3.4.1版本以前默认值为true -->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- 数据库经典列名和Java经典列名的映射(默认值为false) -->
<setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>
mapUnderscoreToCamelCase:简单介绍一下此属性的使用,其他的属性会在后面一一介绍。
在日常Java开发中我们的命名规则驼峰状比如: aaaBbbCcc
而我们的数据库命名规则为: AAA_BBB_CCC,因为命名规则
的不同,在进行Java POJO和数据库表关系映射时,通过反射
就会出现名称对应不上出现属性找不到数据为空的问题,解决方式一般有两种
- ①通过SQL的设置别名
- ②设置mapUnderscoreToCamelCase属性为true
第一种方式我们上面已经用过,接下来我们使用mybatis提供的配置方式解决这个问题,但是一定要注意数据库的命名和Java的命名,一定要遵循自己的命名规范
- マッパー:マッピング ファイルの設定
在mybatis-config.xml配置文件中配置
<mappers>
<!-- 将注册接口的配置文件注册到mybatis的核心配置文件中,
如果有多个映射文件,可以配置多个,还有其他方式会在后面介
绍 -->
<mapper resource="com/im/mapper/UserMapper1.xml" />
<mapper resource="com/im/mapper/UserMapper2.xml" />
<mapper resource="com/im/mapper/UserMapper3.xml" />
</mappers>
第 4 章 列挙型のマッピング
列挙型をマッピングする場合は特別です。Mybatis は、列挙型を文字列または整数型にマッピングする 2 つの方法を公式に提供しています。以下の実装を参照してください。
- テーブルデザイン
数据库表的SQL语句
CREATE TABLE student(
`stu_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`stu_name` VARCHAR(100) NOT NULL COMMENT '学生名',
`gender1` INT NOT NULL COMMENT '性别整数类型',
`gender2` VARCHAR(10) NOT NULL COMMENT '性别字符类型'
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8 COMMENT="学生表";
- データベーステーブルをマップするエンティティクラス
public enum Gender {
MAN("男"),
WOMAN("女"),
NEUTRAL("中性");
private String sex;
private Gender(String sex) {
this.sex = sex;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
<------------------分隔线----------------------->
/**
* 映射数据库student表的类
* @author hu shuang
* @email [email protected]
*/
public class Student {
private Integer stuId;
private String stuName;
//性别映射数据库整数类型
private Gender gender1;
//性别映射数据库字符类型
private Gender gender2;
public Student() {
}
}
- Student テーブルを操作するためのマッパー インターフェイス
public interface StudentMapper {
/*
* 添加一个学生
*/
void addStudent(Student student);
/*
* 更新一个学生
*/
void updateStudent(Student student);
/*
* 获取学生列表
*/
List<Student> getStudents();
}
- 登録インターフェースの XML 設定ファイル
注册接口的xml配置文件
<mapper namespace="com.im.mapper.StudentMapper">
<!--
1、Java枚举值映射到数据库表里面的整型字段时,映射的是枚举的数组下标值
使用typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
2、Java枚举值映射到数据库表里面的varchar类型字段时,使用typeHandler="org.apache.ibatis.type.EnumTypeHandler"
-->
<insert id="addStudent" parameterType="student" useGeneratedKeys="true" keyProperty="stuId">
INSERT INTO student(stu_name,gender1,gender2) VALUES(#{stuName},
#{gender1,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},
#{gender2,typeHandler=org.apache.ibatis.type.EnumTypeHandler})
</insert>
<!-- 查询带有枚举类型的数据时,返回值结果类型不能使用resultType属性设置,需要使用resultMap属性重新进行映射 -->
<resultMap type="student" id="studentMap">
<id property="stuId" column="stu_id"/>
<result property="stuName" column="stu_name"/>
<!-- 映射下标 -->
<result property="gender1" column="gender1" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
<!-- 映射字符串 -->
<result property="gender2" column="gender2" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
<select id="getStudents" resultMap="studentMap">
SELECT * FROM student
</select>
<!-- 更新枚举类型 -->
<update id="updateStudent" parameterType="student">
UPDATE student SET stu_name=#{stuName},gender1=#{gender1,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},gender2=#{gender2,typeHandler=org.apache.ibatis.type.EnumTypeHandler} WHERE stu_id=#{stuId}
</update>
</mapper>
- 列挙型の追加と変更をテストする
public class StudentMapperTest {
/*
* 添加学生
*/
@Test
public void testAddStudent() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setStuName("韩梅梅");
student.setGender1(Gender.MAN);
student.setGender2(Gender.MAN);
mapper.addStudent(student);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 获取学生列表
*/
@Test
public void testGetStudents() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
List<Student> students = mapper.getStudents();
System.out.println(students);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 更新学生信息
*/
@Test
public void testUpdateStudent() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
StudentMapper mapper = session.getMapper(StudentMapper.class);
Student student = new Student();
student.setStuId(1001);
student.setStuName("polly");
student.setGender1(Gender.WOMAN);
student.setGender2(Gender.WOMAN);
mapper.updateStudent(student);
//提交
session.commit();
//关闭会话
session.close();
}
}
第5章 データベース操作のためのSQLマップ(アノテーション)方式
注解方式操作数据库:
1. 不需要注册接口的xml配置文件
2. 直接将SQL写到操作数据库的接口里的每一个方法上
3. 核心配置文件 mapper 直接配置类
<mappers>
<!-- 将注册接口的配置文件注册到mybatis的核心配置文件中 -->
<mapper class="com.im.mapper.UserMapper"/>
</mappers>
- データベースを操作するためのインターフェース
public interface UserMapper {
/*
* 添加用户
*/
@Insert("INSERT INTO user(user_name,create_time) VALUES(#{userName},#{createTime})")
public void addUser(User user);
/*
* 删除用户
*/
@Delete("DELETE FROM user WHERE user_id=#{userId}")
void deleteUser(Integer userId);
/*
* 更新用户
*/
@Update("UPDATE user SET user_name=#{userName},create_time=#{createTime} WHERE user_id=#{userId}")
void updateUser(User user);
/*
* 通过用户ID获取用户信息
*/
@Select("SELECT * FROM user WHERE user_id=#{userId}")
User getUser(Integer userId);
/*
* 获取用户列表
*/
@Select("SELECT * FROM user")
List<User> getUsers();
}
- 単体テストクラス
public class UserMapperTest {
@Test
public void testAddUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
//构建入参
User user = new User();
user.setUserName("张三");
user.setCreateTime(new Date());
mapper.addUser(user);
//提交
session.commit();
//关闭会话
session.close();
}
@Test
public void testDeleteUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
mapper.deleteUser(2);
//提交
session.commit();
//关闭会话
session.close();
}
@Test
public void testUpdateUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
//构建入参
User user = new User();
user.setUserId(5);
user.setUserName("JIM");
user.setCreateTime(new Date());
mapper.updateUser(user);
//提交
session.commit();
//关闭会话
session.close();
}
@Test
public void testGetUsers() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.getUsers();
System.out.println(users);
//提交
session.commit();
//关闭会话
session.close();
}
}
第6章 mybatisログ機能
6.1 ログの概要
mybatis の組み込みログ ファクトリはログ機能を提供し、組み込みログ ファクトリはプロキシとして次のツールのいずれかにログを渡します。
- SLF4J
- Apache Commons ロギング
- ログ4j 2
- Log4j
- JDKのロギング
mybatis の組み込みログ ファクトリは、ランタイム イントロスペクション メカニズムに基づいて適切なログ ツールを選択します。最初に見つかったツールが (上記の順序で) 使用されます。何も見つからない場合、ログは無効になります。
6.2 ログの設定
不少应用服务器(如 Tomcat 和 WebShpere)的类路径中已经包含 Commons Logging,所以在这种配置环境下的MyBatis会把它作为日志工具,记住这点非常重要。这将意味着,在诸如 WebSphere 的环境中,它提供了 Commons Logging的私有实现,你的Log4J配置将被忽略。MyBatis将你的Log4J配置忽略掉是相当令人郁闷的(事实上,正是因为在这种配置环境下,MyBatis 才会选择使用 Commons Logging而不是Log4J)。如果你的应用部署在一个类路径已经包含 Commons Logging 的环境中,而你又想使用其它日志工具,你可以通过在 MyBatis 配置文件mybatis-config.xml里面添加一项setting 来选择别的日志工具。
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J"/>
...
</settings>
</configuration>
logImpl 可选的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是实现了接口org.apache.ibatis.logging.Log的,且构造方法是以字符串为参数的类的完全限定名。
(译者注:可以参考org.apache.ibatis.logging.slf4j.Slf4jImpl.java的实现)
6.3 ログの利用
第1步: 添加jar包
log4j-1.2.17.jar
slf4j-api-1.7.25.jar
slf4j-log4j12-1.7.25.jar
第2步: 添加日志配置文件log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT"
class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="debug" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
第 7 章 動的 SQL
7.1 動的SQLの概要
- 動的SQLの利点
mybatis の強力な機能の 1 つは動的 SQL です。さまざまな条件に応じて SQL を結合した経験のある学生は、条件が多い場合に SQL を結合するのは非常に面倒なことであることを知っているはずですが、mybatis は SQL の結合を非常にうまく解決するのに役立ちます。
- 動的SQLに関係するタグ
- もし
- choose(when, else) (Java の switch ステートメントに似ています)
- トリム(どこで、設定)
- foreach (主にバッチ操作に使用されます)
7.2 動的SQLの使用法
7.2.1 if文(where句の後の条件判定として使用)
- 定数 (1=1) を使用して、部分的な条件一致によって引き起こされる複数の AND によって引き起こされる SQL 構文エラーの問題を解決します。
<!-- if可以作为条件判断 并且使用 1=1 来解决由于条件不匹配而产生的多AND造成SQL语法错误的问题 -->
<select id="getBooks" parameterType="book" resultType="book">
SELECT * FROM book WHERE 1=1
<if test="bookName!=null">AND book_name=#{bookName}</if>
<if test="author!=null and author.name!=null">AND author_name=#{author.name}</if>
<if test="price!=null">AND price=#{price}</if>
</select>
- ラベルを使用して、部分的な条件一致によって引き起こされる複数の AND によって引き起こされる SQL 構文エラーの問題を解決する
<!-- if可以作为条件判断 并且使用<where>标签来解决由于条件不匹配而产生的多AND造成SQL语法错误的问题 -->
<select id="getBooks" parameterType="book" resultType="book">
SELECT * FROM book
<where>
<if test="bookName!=null">AND book_name=#{bookName}</if>
<if test="author!=null and author.name!=null">AND author_name=#{author.name}</if>
<if test="price!=null">AND price=#{price}</if>
</where>
</select>
7.2.2 if文(入力パラメータの判定として文を更新する場合に使用)
- すべてのフィールドが更新されるわけではないため、増分更新中に一部のフィールドに値が割り当てられず、更新されたデータベース内の一部のデータが空白になる問題を解決します。
<update id="updateBook" parameterType="book">
UPDATE book SET
<if test="bookNam!=null">book_name=#{bookName},</if>
<if test="author!=null and author.name!=null">author_name=#{author.name},</if>
<if test="price!=null">price=#{price}</if>
WHERE book_id=#{bookId}
</update>
- 予防
更新時に、更新する必要のないフィールドが原因で SQL ステートメント内にカンマ (,) が複数存在する問題
- ソリューション(ラベル)
<update id="updateBook" parameterType="book">
UPDATE book
<set>
<if test="bookNam!=null">book_name=#{bookName},</if>
<if test="author!=null and author.name!=null">author_name=#{author.name},</if>
<if test="price!=null">price=#{price}</if>
</set>
WHERE book_id=#{bookId}
</update>
7.2.3 選択(いつ、そうでない場合)
用于匹配多个条件中的一个(不常用)
<select id="getBooks" parameterType="book" resultType="book">
SELECT * FROM book WHERE
<choose>
<when test="bookName!=null">book_name=#{bookName}</when>
<when test="author!=null and author.name!=null">author_name=#{author.name}</when>
<when test="price!=null">price=#{price}</when>
<otherwise>
book_id=#{bookId}
</otherwise>
</choose>
</select>
7.2.4 foreach (主にバッチ操作に使用されます)
- バッチ操作マッパー層インターフェース
public interface UserMapper {
/*
* 批量添加
*/
//void batchAddUser(List<User> users); //根据类型匹配
void batchAddUser(@Param("users") List<User> users);//根据名称匹配
/*
* 批量查询
*/
void batchQueryUsers(List<Integer> ids);
/*
* 批量删除
*/
void batchDeleteUsers(List<Integer> ids);
/*
* 批量更新
*/
void batchUpdateUsers(List<User> users);
}
- バッチ追加構文
- 方法 1
方式一:
<!-- 批量添加 -->
<!-- 根据类型匹配 -->
<insert id="batchAddUser" parameterType="user">
INSERT INTO user(user_name,create_time) VALUES
<foreach collection="list" item="item" separator="," >
(#{item.userName},#{item.createTime})
</foreach>
</insert>
- 方法2
<!-- 根据名称匹配 -->
<insert id="batchAddUser" parameterType="user">
INSERT INTO user(user_name,create_time) VALUES
<foreach collection="users" item="item" separator="," >
(#{item.userName},#{item.createTime})
</foreach>
</insert>
- バッチクエリ構文
<!-- 批量查询 -->
<select id="batchQueryUsers" resultType="user">
SELECT * FROM user WHERE user_id IN
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
- 一括削除の構文
<!-- 批量删除 -->
<delete id="batchDeleteUsers">
DELETE FROM user WHERE user_id IN
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
- バッチ更新の構文
- バッチアップデートの設定
mybatis を使用してデータベース データをバッチで更新する場合、URL アドレスの後に true に等しいallowMultiQueries パラメータを追加する必要があります。例: jdbc:mysql
://localhost:3306/mybatis?characterEncoding=utf-8&allowMultiQueries=true
注: を使用してください。 & プロパティー・ファイル内 ;XML 構成ファイル内の & 接続パラメーターを使用する- 文法形式
<!-- 批量更新 -->
<update id="batchUpdateUsers" parameterType="user">
<foreach collection="list" item="item" open="" separator=";" close="">
UPDATE user
<set>
<if test="item.userName!=null">user_name=#{item.userName},</if>
<if test="item.createTime!=null">create_time=#{item.createTime}</if>
</set>
WHERE user_id=#{item.userId}
</foreach>
</update>
- 単体テストコード
public class UserMapperTest {
/*
* 批量添加
*/
@Test
public void testBatchAddUser() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构建入参
List<User> users = new ArrayList<>();
User user1 = new User(null, "EEE", new Date());
User user2 = new User(null, "FFF", new Date());
User user3 = new User(null, "GGG", new Date());
User user4 = new User(null, "HHH", new Date());
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
//调用添加用户方法
userMapper.batchAddUser(users);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 批量查询
*/
@Test
public void testBatchQueryUsers() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构建入参
List<Integer> ids = new ArrayList<>();
ids.add(3);
ids.add(5);
ids.add(7);
//调用批量查询用户方法
List<User> users = userMapper.batchQueryUsers(ids);
System.out.println(users);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 批量删除
*/
@Test
public void testBatchDeleteUsers() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构建入参
List<Integer> ids = new ArrayList<>();
ids.add(3);
ids.add(5);
ids.add(7);
//调用批量删除方法
userMapper.batchDeleteUsers(ids);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 批量更新
*/
@Test
public void testBatchUpdateUsers() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//获取映射器类的对象实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构建入参
List<User> users = new ArrayList<>();
User user1 = new User(4,"MMM", new Date());
User user2 = new User(6,"VVV", new Date());
User user3 = new User(8,"WWW", new Date());
users.add(user1);
users.add(user2);
users.add(user3);
//调用批量更新方法
userMapper.batchUpdateUsers(users);
//提交
session.commit();
//关闭会话
session.close();
}
}
第 8 章 高度なクエリ
8.1 データベーステーブルの作成(部門テーブル/社員テーブル)
CREATE TABLE department(
`dept_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`dept_name` VARCHAR(20) NOT NULL COMMENT '部门名称'
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8 COMMENT="部门表";
CREATE TABLE employee(
`emp_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`emp_name` VARCHAR(20) NOT NULL COMMENT '员工名称',
`salary` DOUBLE(10,2) DEFAULT 0.00 COMMENT '工资',
`dept_id` INT NOT NULL COMMENT '部门ID,关联部门表的主键'
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8 COMMENT="员工表";
//关联
ALTER TABLE employee ADD FOREIGN KEY(dept_id) REFERENCES department(dept_id);
INSERT INTO department(dept_name) VALUES('行政部'),('人事部'),('IT部');
INSERT INTO employee(emp_name,salary,dept_id) VALUES('孙悟空',100.12,1000),('猪八戒',100.12,1001),('沙悟净',100.12,1002);
8.2 データベーステーブルをマップするエンティティクラスの作成
public class Department {
private Integer deptId;
private String deptName;
// 一个部门下有多个员工(一对多关联)
private List<Employee> employees;
public Department() {
}
}
public class Employee {
private Integer empId;
private String empName;
private Double salary;
// 一个员工对应一个部门(一对一关联)
private Department department;
public Employee() {
}
}
8.3 データベースを操作するためのマッパー インターフェイスの作成
- (One to One) 従業員情報を照会し、同時に従業員の部門情報を取得します (1 人の従業員が 1 つの部門に所属します)
- (1 対多) 部門情報を照会し、この部門に属するすべての従業員情報を照会します (部門には複数の従業員がいます)
public interface DepartmentMapper {
/*
* 根据部门ID查询部门详情,不需要将当前部门下的员工列表查出
*/
Department getDepartmentByDeptId(Integer deptId);
/*
* 根据部门ID查询部门详情,需要将当前部门下的员工列表查询出来(方式一 一对多关联查询 单条SQL)
*/
Department getDepartmentByDeptId_(Integer deptId);
/*
* 根据部门ID查询部门详情,需要将当前部门下的员工列表查询出来(方式二 一对多关联查询 多条SQL)
*/
Department getDepartmentByDeptId$(Integer deptId);
}
public interface EmployeeMapper {
/*
* 通过员工ID查询员工信息,同时查询出员工的部门信息( 方式一(单条SQL 关联查询) )
*/
Employee getEmployeeByEmpId(Integer empId);
/*
* 通过员工ID查询员工信息,同时查询出员工的部门信息( 方式二(多条SQL查询) )
*/
Employee getEmployeeByEmpId_(Integer empId);
/*
* 通过部门ID查询员工列表
*/
List<Employee> getEmployeesByDeptId(Integer deptId);
}
8.4 登録インターフェース用の XML 設定ファイルの作成
- 1 対 1 (方法 1) の単一 SQL 関連クエリ
EmployeeMapper.xml
<!-- 一对一 方式一(单条SQL 关联查询) -->
<resultMap type="employee" id="employeeMap">
<!-- 映射主键 -->
<id property="empId" column="emp_id"/>
<!-- 其他映射 -->
<result property="empName" column="emp_name"/>
<result property="salary" column="salary"/>
<!-- 使用 association 进行一对一关联查询 -->
<association property="department" javaType="department">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
</association>
</resultMap>
<select id="getEmployeeByEmpId" parameterType="Integer" resultMap="employeeMap">
SELECT * FROM employee e,department d WHERE e.dept_id=d.dept_id AND e.emp_id=#{empId}
</select>
- 1 対 1 (方法 2) 複数の SQL クエリを個別に実行する
EmployeeMapper.xml
<!-- 一对一 方式二(多条SQL查询) -->
<resultMap type="employee" id="employeeMap_">
<id property="empId" column="emp_id"/>
<result property="empName" column="emp_name"/>
<result property="salary" column="salary"/>
<!--
当使用方式二时,association标签内有一个select属性,需要在此调用DepartmentMapper xml
配置文件中的statement进行二次查询
com.im.mapper.DepartmentMapper.getDepartmentByDeptId:DepartmentMapper.xml中的namespace(接口全类名)+id属性(方法名字)
-->
<association property="department" javaType="department" column="dept_id" select="com.im.mapper.DepartmentMapper.getDepartmentByDeptId"/>
</resultMap>
<select id="getEmployeeByEmpId_" parameterType="Integer" resultMap="employeeMap_">
SELECT * FROM employee WHERE emp_id=#{empId}
</select>
DepartmentMapper.xml
<select id="getDepartmentByDeptId" parameterType="Integer" resultType="department">
SELECT * FROM department WHERE dept_id=#{deptId}
</select>
- 1 対多 (方法 1) の単一 SQL 関連クエリ
DepartmentMapper.xml
<!-- 根据部门ID查询部门详情,需要将当前部门下的员工列表查询出来(方式一 一对多关联查询 单条SQL) -->
<resultMap type="department" id="departmentMap_">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<!-- 一对多关联查询多的一方使用collection标签 ofType:集合中的泛型类型;property:多的一方属性名 -->
<collection property="employees" ofType="employee">
<id property="empId" column="emp_id"/>
<result property="empName" column="emp_name"/>
<result property="salary" column="salary"/>
</collection>
</resultMap>
<select id="getDepartmentByDeptId_" parameterType="Integer" resultMap="departmentMap_">
SELECT * FROM department d,employee e WHERE d.dept_id=e.dept_id AND d.dept_id=#{deptId}
</select>
- 1 対多 (方法 2) 複数の SQL クエリを個別に実行する
DepartmentMapper.xml
<!-- 根据部门ID查询部门详情,需要将当前部门下的员工列表查询出来(方式二 一对多关联查询 多条SQL) -->
<resultMap type="department" id="departmentMap$">
<id property="deptId" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<!-- 一对多关联查询多的一方使用collection标签 ofType:集合中的泛型类型;property:多的一方属性名 column:关联关系的键 -->
<collection property="employees" ofType="employee" column="dept_id" select="com.im.mapper.EmployeeMapper.getEmployeesByDeptId"/>
</resultMap>
<select id="getDepartmentByDeptId$" parameterType="Integer" resultMap="departmentMap$">
SELECT * FROM department WHERE dept_id=#{deptId}
</select>
EmployeeMapper.xml
<select id="getEmployeesByDeptId" parameterType="Integer" resultType="employee">
SELECT * FROM employee WHERE dept_id=#{deptId}
</select>
8.5 単体テストクラス
- EmployeeMapperTest.java
public class EmployeeMapperTest {
/*
* 一对一 方式一(使用一条SQL语句关联查询)
*/
@Test
public void testGetEmployeeByEmpId() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.getEmployeeByEmpId(1000);
System.out.println(employee);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 一对一 方式二(多条SQL分别查询)
*/
@Test
public void testGetEmployeeByEmpId_() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
Employee employee = employeeMapper.getEmployeeByEmpId_(1000);
System.out.println(employee);
//提交
session.commit();
//关闭会话
session.close();
}
}
- 部門マッパーテスト.java
public class DepartmentMapperTest {
/*
* 一对多 方式一(使用一条SQL语句关联查询)
*/
@Test
public void testGetDepartmentByDeptId_() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
Department department = mapper.getDepartmentByDeptId_(1000);
System.out.println(department);
//提交
session.commit();
//关闭会话
session.close();
}
/*
* 一对多 方式二(多条SQL单独查询)
*/
@Test
public void testGetDepartmentByDeptId$() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
DepartmentMapper mapper = session.getMapper(DepartmentMapper.class);
Department department = mapper.getDepartmentByDeptId$(1000);
System.out.println(department);
//提交
session.commit();
//关闭会话
session.close();
}
}
8.6 相関クエリのバグ拡張
関連付け関係のある複数のPOJO間で同じ属性名が存在する問題によるマッピングデータエラーのバグ対応と解決方法
- データベーステーブルの作成
CREATE TABLE tb_key(
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`name` VARCHAR(20) NOT NULL COMMENT '钥匙名称',
`lock_id` INT NOT NULL COMMENT '锁ID关联锁表的主键'
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8 COMMENT="钥匙表";
CREATE TABLE tb_lock(
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`name` VARCHAR(20) NOT NULL COMMENT '锁名称'
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8 COMMENT="锁表";
//关联
ALTER TABLE tb_key ADD FOREIGN KEY(lock_id) REFERENCES tb_lock(id);
INSERT INTO tb_key(name,lock_id) VALUES("铁牛钥匙",1000);
INSERT INTO tb_lock(name) VALUES('铁牛锁');
- データベーステーブルをマップするエンティティクラスを作成する
/*
* 锁类
*/
public class TbLock {
private Integer id;
private String name;
public TbLock() {
}
}
/*
* 钥匙类
*/
public class TbKey {
private Integer id;
private String name;
//一把钥匙只能开一把锁 一对一关联
private TbLock tbLock;
public TbKey() {
}
}
- データベーステーブルを操作するマッパーインターフェイスを作成する
public interface TbKeyMapper {
/*
* 通过钥匙ID钥匙信息以及锁的信息
*/
TbKey getKeyInfo(Integer keyId);
}
- データベーステーブルインターフェースを登録・操作するためのXML設定ファイルを作成します。
<mapper namespace="com.im.mapper.TbKeyMapper">
<resultMap type="tbKey" id="tbKeyMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="tbLock" javaType="tbLock">
<id property="id" column="id"/>
<result property="name" column="name"/>
</association>
</resultMap>
<select id="getKeyInfo" parameterType="Integer" resultMap="tbKeyMap">
SELECT * FROM tb_key tk,tb_lock tl WHERE tk.lock_id=tl.id AND tk.id=#{keyId}
</select>
</mapper>
- テストクラスを書く
@Test
public void testGetKeyInfo() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
TbKeyMapper keyMapper = session.getMapper(TbKeyMapper.class);
TbKey keyInfo = keyMapper.getKeyInfo(1000);
System.out.println(keyInfo);
//提交
session.commit();
//关闭会话
session.close();
}
- 結果分析
その結果、マッピングが間違っており、キーとロックの情報が同じであることがわかります。
TbKey [id=1000, name=Tie Niu Key, tbLock=TbLock [id=1000, name=Tie Niu Key]]
これは、2 つの JavaBean クラス TbKey と TbLock の属性名が同じであるためです。関連付けタグを使用して Java オブジェクトをネーム マッピングでマッピングしていることがわかります。2 つの JavaBean 属性名が同じ場合、マッピングが不明確であるという問題があります。
- 解決策: 複数 SQL 結合クエリの方法を使用する
<resultMap type="tbKey" id="tbKeyMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="tbLock" javaType="tbLock" column="lock_id" select="com.im.mapper.TbLockMapper.getLockInfo"/>
</resultMap>
<select id="getKeyInfo" parameterType="Integer" resultMap="tbKeyMap">
SELECT * FROM tb_key WHERE id=#{keyId}
</select>
第9章 mybatisの遅延ロード
9.1 遅延ロードとは何ですか
遅延読み込み (遅延読み込みとも呼ばれます) とは、データを取得するときに、一部のデータはリアルタイムで取得する必要はありませんが、必要なときに取得されることを意味します。このデータの読み込み方法は遅延読み込みと呼ばれます。
9.2 遅延ロードの使用
- jar パッケージを追加します。Maven 依存関係の場合は追加できません。
cglib-2.2.2.jar
asm-3.3.1.jar
- mybatis グローバル設定ファイルで遅延ロードを有効にする
積極的なLazyLoadingをオフにし、
遅延ロードをオンにしますlazyLoadingEnabled
<settings>
<!-- 设置经典Java命名规则和经典数据库命名规则的自动映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启懒加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 关闭延时加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
- 特定の関係では、項目のスイッチ状態は fetchType 属性を設定することでオーバーライドできます。
- 特定の関連付けとは、複数テーブル結合クエリの方法ではなく、関連付けマッピング タグ
またはその中の select 属性の使用を指します。- または の fetchType 属性によって遅延に設定できます。
第10章 mybatisキャッシュ
10.1 キャッシュの長所と短所
利点: データベースの読み取り操作が軽減され、データベースの負荷が軽減され、応答が高速化されます。
欠点: データの不整合が発生し、コストが増加する可能性があります。
10.2 mybatisのレベル1キャッシュ
- レベル1キャッシュ機能
- レベル 1 キャッシュはデフォルトで有効になっています
- デフォルトでは、第 1 レベルのキャッシュは SqlSession レベルです。
- L1キャッシュを検証する
- 1 つの SqlSession で同じ条件で複数回クエリを実行すると、ログに SQL が 1 つだけ出力されることがわかり、キャッシュがあることがわかります。
- 複数の SqlSession の下で、同じ条件に従ってクエリを実行し、一次キャッシュが SqlSession レベルにあることを示す複数の SQL を出力します。SqlSession オブジェクトが革新的に作成された後、キャッシュは無効になります。
- レベル 1 キャッシュ無効化モード
- sqlSession.clearCache() を使用してキャッシュを更新します
- SqlSessionを閉じた後に再度開く
- SqlSession は、追加、削除、変更後にキャッシュをクリアします。
10.3 mybatisの2次キャッシュ
- L2キャッシュ機能
- 2次キャッシュには手動構成が必要です
- 2 番目のレベルのキャッシュは SqlSessionFactory レベルにあります
- 2次キャッシュの使用量
①在myabtis-config.xml全局的开启二级缓存
<settings>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
②SQL map映射文件中添加<cache/>
<cache/>标签中属性的介绍:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
eviction: 缓存的回收策略
—>LRU – 最近最少使用的:移除最长时间不被使用的对象
—>FIFO – 先进先出: 按对象进入缓存的顺序来移除它们
—>SOFT – 软引用: 移除基于垃圾回收器状态和软引用规则的对象
—>WEAK – 弱引用: 更积极地移除基于垃圾收集器状态和弱引用规则的对象
flushInterval: 刷新间隔,默认不刷新,可以设置任意的正整数,毫秒数
size: 引用数目->可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目,默认值是1024。
readOnly: 是否只读默认是false->只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(映射数据库的实体类必须实现序列化) 。这会慢一些,但是安全,因此默认是 false
- 2次キャッシュ設定成功フラグ
キャッシュ ヒット率はログに表示され、各クエリの後にトランザクションをコミットする必要があります。コミットしないと、2 次キャッシュが機能せず、キャッシュ ヒット率は変わりません。キャッシュ ヒット率 [com.im.mapper.UserMapper
] ]:0.0
10.4 サードパーティのキャッシュ ehcache の統合
2次キャッシュ製品ehcacheを使用する手順
- jar パッケージまたは依存関係を追加する
ehcache-2.10.4.jar
mybatis-ehcache-1.0.0.jar
-
ehcache 製品構成ファイル ehcache.xml を追加します
-
Ehcache の構成
在SQL map 文件中配置<cache/>标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<!-- 缓存创建以后,最后一次访问缓存,间隔多久缓存失效(单位s) -->
<property name="timeToIdleSeconds" value="3600"/>
<!-- 缓存创建日期起到失效时的时间间隔(单位s) -->
<property name="timeToLiveSeconds" value="3600"/>
<!-- 堆内存中缓存对象数(0:没有限制) -->
<property name="maxEntriesLocalHeap" value="1000"/>
<!-- 磁盘中的对象数,默认为0不限制 -->
<property name="maxEntriesLocalDisk" value="1000000"/>
<!-- 内存存储与释放策略(FIFO:先进先出,LFU:一直以来最少被使用的,LRU:最近最少使用的) -->
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
第 11 章 MYSQL ページネーション
11.1 ページングの準備
- データベースを操作するためのインターフェースコード
/**
* 操作数据库表的接口
*/
public interface UserMapper {
/*
* 原生SQL分页
* @Param:方法入参为多个时要使用此注解指定入参,否则mybatis表达式(#{xxx})会找不到方法入参
*/
List<User> getUserPage(@Param("offset")int offset,@Param("pageSize")int pageSize);
/*
* 分页插件分页
*/
List<User> getUserPage_();
}
- 登録インターフェースの 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.im.mapper.UserMapper">
<!-- 原生分页 -->
<select id="getUserPage" resultType="user">
SELECT * FROM user LIMIT #{offset},#{pageSize}
</select>
<!-- 插件分页,pageHelper插件分页时,方法不需要传任何入参 -->
<select id="getUserPage_" resultType="user">
SELECT * FROM user
</select>
</mapper>
11.2 ネイティブのページネーション
/*
* 原生分页
*/
@Test
public void testGetUserPage() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
int pageNo=3;//当前页
int pageSize=2;//每页显示的条数
//mysql分页的第一个参数,转换公式
int offset=(pageNo-1)*pageSize;
List<User> page = mapper.getUserPage(offset, pageSize);
System.out.println(page);
//提交
session.commit();
//关闭会话
session.close();
}
11.3 ページネーションプラグイン (PageHelper)
- jar パッケージまたは依存関係を追加する
jsqlparser-0.9.5.jar
pagehelper-5.1.2.jar
- mybatis-config.xml で PageHelper を構成する
<!-- 配置分页插件pageHelper -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--
分页合理化参数,默认值为false。当该参数设置为 true 时,
pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),
会查询最后一页。默认false 时,直接根据参数进行查询
-->
<property name="reasonable" value="true"/>
<!-- 支持合法的参数化,设置这个属性以及下面的属性,可以设置方法的入参 -->
<property name="supportMethodsArguments" value="true"/>
<!-- 参数化的key值 -->
<property name="params" value="pageNum=pageNumKey;pageSize=pageSizeKey;"/>
</plugin>
</plugins>
- Junit 単体テスト
/*
* pageHelper分页
*/
@Test
public void testGetUserPage_() throws IOException {
//加载外部属性资源文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//创建SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
//在查询全部数据之前直接调用PageHelper.startPage(2, 2);方法进行分页
//注意不能再两个方法之间插入其他的代码方法入参为第一个:pageNo;第二个:pageSize
PageHelper.startPage(2, 2);
List<User> page_ = mapper.getUserPage_();
for (User user : page_) {
System.out.println(user);
}
//提交
session.commit();
//关闭会话
session.close();
}
第12章 mybatisとSpringフレームワークの統合
Spring + mybatis フレームワーク統合の
統合手順:
- Javaの通常プロジェクトを作成します(ページがないためWebプロジェクトはありません)
- jar パッケージ ディレクトリまたは Maven 依存関係を追加する
commons-logging-1.2.jar
druid-1.1.6.jar
jsqlparser-0.9.5.jar
log4j-1.2.17.jar
mybatis-3.4.6.jar
mybatis-spring-1.3.1.jar
mysql-connector-java-5.1.7-bin.jar
pagehelper-5.1.2.jar
slf4j-api-1.7.25.jar
slf4j-log4j12-1.7.25.jar
spring-aop-4.3.10.RELEASE.jar
spring-aspects-4.3.10.RELEASE.jar
spring-beans-4.3.10.RELEASE.jar
spring-context-4.3.10.RELEASE.jar
spring-context-support-4.3.10.RELEASE.jar
spring-core-4.3.10.RELEASE.jar
spring-expression-4.3.10.RELEASE.jar
spring-jdbc-4.3.10.RELEASE.jar
spring-orm-4.3.10.RELEASE.jar
spring-oxm-4.3.10.RELEASE.jar
spring-test-4.3.10.RELEASE.jar
spring-tx-4.3.10.RELEASE.jar
- jdbc.properties 構成ファイルを作成する
jdbc_user=root
jdbc_password=root
jdbc_url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
- mybatis-config.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="cacheEnabled" value="true"/>
<!-- 开启驼峰命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 配置分页插件pageHelper -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--
分页合理化参数,默认值为false。当该参数设置为 true 时,
pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),
会查询最后一页。默认false 时,直接根据参数进行查询
-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
- applicationContext.xml 構成ファイルを作成する
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 1.导入外部属性资源文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 2.扫描需要扫描的包 -->
<context:component-scan base-package="com.sc" />
<!-- 3.配置数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_user}" />
<property name="password" value="${jdbc_password}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="false" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="stat" />
</bean>
<!-- 4.配置SqlSessionFactory -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.sc.entity" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>
<!-- 5.配置平台事务管理理器器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 6.开启基于注解的声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 7.注册mybatis接⼝口加⼊入到Spring IOC容器器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<property name="basePackage" value="com.sc.mapper" />
<property name="annotationClass" value="org.springframework.stereotype.Repository" />
</bean>
</beans>
- log4j.xml設定ファイルを追加
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT"
class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="debug" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
第 13 章 Spring フレームワークの単体テスト
Spring フレームワークと mybatis フレームワークの統合が完了したら、統合が成功したかどうかをテストする必要があります。次に、テストが必要です。テストでは Spring フレームワークの spring-tx-4.3.10.RELEASE.jar 依存関係を使用します。単体テスト用。
- 上記の mybatis の例を使用してテストします。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= {
"classpath:applicationContext.xml"})
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void test01() {
List<User> users = userMapper.getUsers();
System.out.println(users);
}
}
第 14 章 mybatis マッピング MYSQL5.7 の新しい JSON データ型
14.1 mybatis 5.7 json データ型の概要
MYSQL5.7 の GA バージョンでは、json 形式のデータのサポートが開始されました。json
形式には 2 つのタイプがあります: 1 つは単一オブジェクト {}、もう 1 つはコレクション形式 []
14.2 Java オブジェクトと json データ間の相互通信
mybatis が Java オブジェクトを json データ形式でデータベースに保存する方法と、データベース内の json データ形式をクエリして Java オブジェクトとして保存する方法をご覧ください。
- データベーステーブルの作成
CREATE TABLE tb_order(
`order_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`users` json NOT NULL,
`user` json NOT NULL
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=UTF8;
- データベーステーブルをマップするJavaエンティティクラスを作成する
//测试数据库两种数据类型
public class Order {
private Integer orderId;
//[{"id":1001,"name":"李雷"},{"id":1001,"name":"李雷"}]
private List<User> users;
//{"id":1001,"name":"李雷"}
private User user;
}
public class User {
// 用户ID
private Integer userId;
// 用户名
private String userName;
}
- JSON および POJO 変換用のカスタム型コンバーターを作成する
- コレクション型ハンドラー(コレクションデータの処理) JsonArrayTypeHandler.java
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.alibaba.fastjson.JSON;
import com.im.entity.User;
/*
* 数组类型的相互转换
* JSON转换使用的是阿里巴巴的fastjson
*/
public class JsonArrayTypeHandler extends BaseTypeHandler<List<User>> {
/*
* 使用列名获取数据库中保存的json数据
* 并将其数据类型转换成List集合
*/
@Override
public List<User> getNullableResult(ResultSet arg0, String arg1) throws SQLException {
String string = arg0.getString(arg1);
return JSON.parseObject(string, List.class);
}
/**
* 使用索引获取数据库中保存的json数据
* 并将其数据类型转换成List集合
*/
@Override
public List<User> getNullableResult(ResultSet arg0, int arg1) throws SQLException {
String string = arg0.getString(arg1);
return JSON.parseObject(string, List.class);
}
/**
* 使用索引获取数据库中保存的json数据
* 并将其数据类型转换成List集合
*/
@Override
public List<User> getNullableResult(CallableStatement arg0, int arg1) throws SQLException {
String string = arg0.getString(arg1);
return JSON.parseObject(string,List.class);
}
/**
* 将集合的实体对象转换成JSON保存到数据库中
*/
@Override
public void setNonNullParameter(PreparedStatement arg0, int arg1, List<User> arg2, JdbcType arg3)
throws SQLException {
arg0.setString(arg1, JSON.toJSONString(arg2));
}
}
- 単一オブジェクト ハンドラー (単一オブジェクトの処理) JsonTypeHandler.java
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.alibaba.fastjson.JSON;
import com.im.entity.User;
/**
* 自定义类型处理器
* @author hushuang
* json转换使用阿里巴巴的fastjson
*/
public class JsonTypeHandler extends BaseTypeHandler<User> {
@Override
public User getNullableResult(ResultSet arg0, String arg1) throws SQLException {
return JSON.parseObject(arg0.getString(arg1), User.class);
}
@Override
public User getNullableResult(ResultSet arg0, int arg1) throws SQLException {
return JSON.parseObject(arg0.getString(arg1), User.class);
}
@Override
public User getNullableResult(CallableStatement arg0, int arg1) throws SQLException {
return JSON.parseObject(arg0.getString(arg1), User.class);
}
@Override
public void setNonNullParameter(PreparedStatement arg0, int arg1, User arg2, JdbcType arg3) throws SQLException {
arg0.setString(arg1, JSON.toJSONString(arg2));
}
}
- カスタム型コンバーターを登録する
在mybatis-config.xml配置文件中注册
<typeHandlers>
<typeHandler handler="com.im.handler.JsonTypeHandler" />
<typeHandler handler="com.im.handler.JsonArrayTypeHandler" />
</typeHandlers>
- アノテーション操作インターフェースの 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.im.mapper.OrderMapper">
<!-- 测试插入 -->
<insert id="addOrder" parameterType="order">
INSERT INTO tb_order(users,user)
VALUES(#{users,typeHandler=com.im.handler.JsonArrayTypeHandler},#{user,typeHandler=com.im.handler.JsonTypeHandler})
</insert>
<!-- 测试查询 -->
<resultMap type="order" id="orderMap">
<id property="orderId" column="order_id"/>
<result property="users" column="users" typeHandler="com.im.handler.JsonArrayTypeHandler"/>
<result property="user" column="user" typeHandler="com.im.handler.JsonTypeHandler"/>
</resultMap>
<select id="getOrder" resultMap="orderMap">
SELECT * FROM tb_order WHERE order_id=#{id}
</select>
</mapper>
第 15 章 関連文書
Mybatis 中国語公式 Web サイトのアドレス: https://mybatis.org/mybatis-3/zh/index.html
Druid 中国語公式 Web サイトのアドレス: https://github.com/alibaba/druid/wiki/%E5%B8%B8% E8% A7%81%E9%97%AE%E9%A2%98
pageHelper 公式 Web サイトのアドレス: https://pagehelper.github.io/docs/howtouse/ehcache
公式 Web サイトのアドレス: http://mybatis.org/ehcache -キャッシュ/