MyBatis基础知识汇总
MyBatis
1、MyBatis 概述
1.1、MyBatis简介
- MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
- MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录.
1.2、MyBatis历史
- 原是apache的一个开源项目iBatis,
- 2010年6月这个项目由apache software foundation 迁移到了google code,随着开发团队转投Google Code旗下,ibatis3.x正式更名为Mybatis ,
- 2013年11月代码迁移到Github(下载地址 -- https://github.com/mybatis/mybatis-3/ )。
- iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
- iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
1.3、为什么要用MyBatis
-
MyBatis是一个半自动化的持久化层框架。
-
JDBC
-
- SQL夹在Java代码块里,耦合度高导致硬编码内伤
- 维护不易且实际开发需求中sql是有变化,频繁修改的情况多见
-
Hibernate和JPA
-
- 长难复杂SQL,对于Hibernate而言处理也不容易
- 内部自动生产的SQL,不容易做特殊优化。
- 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。 导致数据库性能下降。
-
对开发人员而言,核心sql还是需要自己优化
-
MyBatis
-
- sql和java编码分开,功能边界清晰,一个专注业务、 一个专注数据。
2、HelloMyBatis
2.1、创建数据库环境
-- 初始化脚本
-- 1 创建数据库
drop database if exists mybatis;
create database if not exists mybatis;
use mybatis;
-- 2 创建数据表
create table if not exists `sy_user`
(
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_code` varchar(20) DEFAULT NULL COMMENT '用户编码',
`user_name` varchar(20) DEFAULT NULL COMMENT '用户姓名',
`sex` varchar(20) DEFAULT NULL COMMENT '性别',
`brithday` date DEFAULT NULL COMMENT '生日',
PRIMARY KEY (`id`)
);
-- 3 插入数据
INSERT INTO `mybatis`.`sy_user`(`user_code`, `user_name`, `sex`, `brithday`)
VALUES ('0001', '张三', '男', '2019-12-31');
INSERT INTO `mybatis`.`sy_user`(`user_code`, `user_name`, `sex`, `brithday`)
VALUES ('0002', '李斯', '女', '1989-12-31');
-- 4 查询数据
select * from sy_user;
2.2、引入Jar包
<dependencies>
<!-- mybatis包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!-- mysql数据库链接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!-- 日志包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
2.3、编写User实体
package demo.mybatis.entity;
import java.util.Date;
public class User {
private long id;
private String userCode;
private String userName;
private String sex;
private Date brithday;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBrithday() {
return brithday;
}
public void setBrithday(Date brithday) {
this.brithday = brithday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userCode='" + userCode + '\'' +
", userName='" + userName + '\'' +
", sex='" + sex + '\'' +
", brithday=" + brithday +
'}';
}
}
2.4、配置log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
2.5、配置jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT&useSSL=false&allowPublicKeyRetrieval=true
jdbc.initialSize=10
jdbc.maxActive=20
2.6、配置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="demo.mybatis.dao.UserDao">
<select id="selectUserById" parameterType="int" resultType="demo.mybatis.entity.User">
select id, user_code userCode, user_name userName,brithday from sy_user where id = #{value}
</select>
</mapper>
2.7、配置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>
<properties resource="jdbc.properties"/>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2.8、单元测试
package demo.mybatis;
import demo.mybatis.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class Test01 {
SqlSession sqlSession;
@Before
public void init() {
// 1 读取mybatis的核心配置文件
InputStream is = null;
try {
is = Resources.getResourceAsStream("mybatis-config.xml");
// 2 根据全局配置文件,利用SqlSessionFactoryBuilder创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
// 3 使用SqlSessionFactory获取sqlSession对象。一个SqlSession对象代表和数据库的一次会话。
sqlSession = sqlSessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void T01() {
User user = sqlSession.selectOne("demo.mybatis.dao.UserDao.selectUserById",1);
System.out.println(user);
}
}
3、HelloMyBatis优化版
通过创建一个Dao接口,编写增删改查接口,同时编写其具体实现类。
3.1、编写UserDao接口
package demo.mybatis.dao;
import demo.mybatis.entity.User;
import java.util.List;
public interface UserDao {
// 保存用户
public int saveUser(User user);
// 更新用户
public int updateUser(User user);
// 根据id删除用户
public int deleteUserById(int id);
// 根据id搜索用户
public User findUserById(int id);
// 搜索全部用户
public List<User> findUsers();
}
3.2、编写UserDaoImpl实现类
package demo.mybatis.dao.Impl;
import demo.mybatis.dao.UserDao;
import demo.mybatis.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
public class UserDaoImpl implements UserDao {
SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
public int saveUser(User user) {
SqlSession sqlSession = sqlSessionFactory.openSession();
int result = 0;
try {
result = sqlSession.insert("demo.mybatis.dao.UserDao.saveUser", user);
//提交事务
sqlSession.commit();
} finally {
sqlSession.close();
}
return result;
}
public int updateUser(User user) {
SqlSession sqlSession = sqlSessionFactory.openSession();
int result = 0;
try {
result = sqlSession.update("demo.mybatis.dao.UserDao.updateUser", user);
//提交事务
sqlSession.commit();
} finally {
sqlSession.close();
}
return result;
}
public int deleteUserById(int id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
int result = 0;
try {
result = sqlSession.update("demo.mybatis.dao.UserDao.deleteUserById", id);
sqlSession.commit(); //提交事务
} finally {
sqlSession.close();
}
return result;
}
public User findUserById(int id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
User result = null;
try {
result = sqlSession.selectOne("demo.mybatis.dao.UserDao.findUserById", id);
} finally {
sqlSession.close();
}
return result;
}
public List<User> findUsers() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> result = null;
try {
result = sqlSession.selectList("demo.mybatis.dao.UserDao.findUsers");
} finally {
sqlSession.close();
}
return result;
}
}
3.3、编写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="demo.mybatis.dao.UserDao">
<select id="selectUserById" parameterType="int" resultType="demo.mybatis.entity.User">
select id, user_code userCode, user_name userName,sex, brithday from sy_user where id = #{value}
</select>
<insert id="saveUser" parameterType="demo.mybatis.entity.User">
insert into sy_user(user_code , user_name ,sex,brithday) values(#{userCode},#{userName},#{sex},#{brithday})
</insert>
<update id="updateUser" parameterType="demo.mybatis.entity.User">
update sy_user
set user_code = #{userCode},
user_name =#{userName},
sex = #{sex}
where
id = #{id}
</update>
<delete id="deleteUserById" parameterType="int">
delete from sy_user where id = #{id}
</delete>
<select id="findUserById" parameterType="int" resultType="demo.mybatis.entity.User">
select id, user_code userCode, user_name userName,sex, brithday from sy_user where id = #{value}
</select>
<select id="findUsers" resultType="demo.mybatis.entity.User">
select id, user_code userCode, user_name userName,sex, brithday from sy_user
</select>
</mapper>
3.3、单元测试
package demo.mybatis;
import demo.mybatis.dao.Impl.UserDaoImpl;
import demo.mybatis.dao.UserDao;
import demo.mybatis.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
public class Test02 {
UserDao userDao;
@Before
public void setUpBeforeClass() throws Exception {
String url = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(url);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
userDao = new UserDaoImpl(sqlSessionFactory);
}
@Test
public void testSaveUser() {
User user = new User();
user.setSex("女");
user.setUserCode("0003");
user.setUserName("花木兰");
user.setBrithday(new Date());
System.out.println(userDao.saveUser(user));
System.out.println(user);
}
@Test
public void testUpdateUser() {
User user = new User();
user.setId(1);
user.setSex("女");
user.setUserCode("0004");
user.setUserName("花木兰2");
user.setBrithday(new Date());
userDao.updateUser(user);
System.out.println(user);
}
@Test
public void testDeleteUserById() {
System.out.println("更新条数:" + userDao.deleteUserById(2));
}
@Test
public void testFindUserById() {
System.out.println(userDao.findUserById(1));
}
@Test
public void testFindUsers() {
System.out.println(userDao.findUsers());
}
}
4、Mapper接口方式
- Mapper接口方式的编程,需要先有一个接口。这个接口的命名一般是xxxxMapper。
- User模块的Mapper,接口命名为UserMapper。
- Book模块的Mapper,接口命名为BookMapper。
Mapper接口开发有四个开发规范必须遵守
- 1、对应的mapper配置文件的namespace属性值必须是Mapper接口的全类名。
- 2、Mapper接口中的方法名必须与mapper配置文件中对应的id值相同。
- 3、Mapper接口的方法的参数类型必须与mapper配置文件中配置的parameterType类型匹配上
- 4、Mapper接口的方法返回值类型必须与mapper配置文件中配置的resultType类型匹配上
4.1、编写UserDao接口
package demo.mybatis.dao;
import demo.mybatis.entity.User;
import java.util.List;
public interface UserDao {
// 保存用户
public int saveUser(User user);
// 更新用户
public int updateUser(User user);
// 根据id删除用户
public int deleteUserById(int id);
// 根据id搜索用户
public User findUserById(int id);
// 搜索全部用户
public List<User> findUsers();
}
4.2、修改UserMapper.xml
- 修改原来UserMapper.xml配置文件的 namespace属性值为刚创建的UserDao接口的全类名
<mapper namespace="demo.mybatis.dao.UserDao">
4.3、单元测试
package demo.mybatis;
import demo.mybatis.dao.UserDao;
import demo.mybatis.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
public class Test03 {
UserDao userDao;
SqlSession session;
@Before
public void setUpBeforeClass() throws Exception {
String url = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(url);
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
userDao = session.getMapper(UserDao.class);
}
@Test
public void testSaveUser() {
User user = new User();
user.setSex("女");
user.setUserCode("0003");
user.setUserName("花木兰");
user.setBrithday(new Date());
System.out.println(userDao.saveUser(user));
System.out.println(user);
session.commit();
}
@Test
public void testUpdateUser() {
User user = new User();
user.setId(1);
user.setSex("女");
user.setUserCode("0004");
user.setUserName("花木兰2");
user.setBrithday(new Date());
userDao.updateUser(user);
System.out.println(user);
session.commit();
}
@Test
public void testDeleteUserById() {
System.out.println("更新条数:" + userDao.deleteUserById(2));
session.commit();
}
@Test
public void testFindUserById() {
System.out.println(userDao.findUserById(1));
}
@Test
public void testFindUsers() {
System.out.println(userDao.findUsers());
}
}
5、MyBatis全局配置文件说明
MyBatis全局配置文件(mybatis-config.xml)文件结构如下
configuration 配置
properties 属性
settings 设置
typeAliases 类型命名
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
databaseIdProvider 数据库厂商标识
mappers 映射器
5.1、properties 属性
properties属性都是可外部配置且可动态替换的,既可以在典型的Java属性文件中配置,亦可通过properties元素的子元素(resource)来传递。
使用的时候,用${name} 进行输出
- 特别说明:引入的jdbc.properties属性文件中的信息,会覆盖掉原来使用property标签定义的属性值。
<properties resource="jdbc.properties">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/stock?serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
<environments default="development">
<!-- environment 标签用来配置一个环境
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/> <!-- 连接数据库的驱动类 -->
<property name="url" value="${url}"/> <!-- 数据库访问地址 -->
<property name="username" value="${user}"/> <!-- 数据库用户名 -->
<property name="password" value="${password}"/> <!-- 数据库密码 -->
</dataSource>
</environment>
</environments>
5.2、settings设置
<!-- 配置全局mybatis的配置 -->
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 启用驼峰标识 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
| 设置参数 | 描述 | 有效值 | 默认值 |
|---|---|---|---|
| cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关。 | true | false | true |
| lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 |
true | false | false |
| aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 | true | false | true |
| multipleResultSetsEnabled | 是否允许单一语句返回多结果集(需要兼容驱动)。 | true | false | true |
| useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true | false | true |
| useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 | true | false | False |
| autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
| autoMappingUnknownColumnBehavior | Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target.·NONE`: Do nothing·WARNING: Output warning log (The log level of```'org.apache.ibatis.session.AutoMappingUnknownColumnBehavior'must be set to WARN`)·FAILING: Fail mapping (Throw ```SqlSessionException) |
NONE, WARNING, FAILING | NONE |
| defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); BATCH 执行器将重用语句并执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
| defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | Any positive integer | Not Set (null) |
| defaultFetchSize | Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a query setting. | Any positive integer | Not Set (null) |
| safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds)。 If allow, set the false. | true | false | False |
| safeResultHandlerEnabled | 允许在嵌套语句中使用分页(ResultHandler)。 If allow, set the false. | true | false | True |
| mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true | false | False |
| localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 | SESSION | STATEMENT | SESSION |
| jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如NULL、VARCHAR 或 OTHER。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
| lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载。 | A method name list separated by commas | equals,clone,hashCode,toString |
| defaultScriptingLanguage | 指定动态 SQL 生成的默认语言。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
| callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 | true | false | false |
| logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | Any String | Not set |
| logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | Not set |
| proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 or above) |
| vfsImpl | Specifies VFS implementations | Fully qualified class names of custom VFS implementation separated by commas. | Not set |
| useActualParamName | Allow referencing statement parameters by their actual names declared in the method signature. To use this feature, your project must be compiled in Java 8 with -parameters option. (Since: 3.4.1) |
true | false | true |
5.3、typeAliases 别名处理器
5.3.1、系统提示的预定义别名
- 已经为许多常见的 Java 类型内建了相应的类型别名。它们都是大小写不敏感的,需要注意的是由基本类型名称重复导致的特殊处理。
| 别名 | 映射的类型 | 别名 | 映射的类型 | 别名 | 映射的类型 | 别名 | 映射的类型 |
|---|---|---|---|---|---|---|---|
| _byte | byte | string | String | float | Float | object | Object |
| _long | long | byte | Byte | boolean | Boolean | map | Map |
| _short | short | long | Long | date | Date | hashmap | HashMap |
| _int | int | short | Short | decimal | BigDecimal | list | List |
| _integer | int | int | Integer | bigdecimal | BigDecimal | arraylist | ArrayList |
| _double | double | integer | Integer | integer | Integer | collection | Collection |
| _float | float | double | Double | double | Double | iterator | Iterator |
| _boolean | boolean |
5.3.2、自定义别名
类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类。typeAliases别名处理器
<typeAliases>
<typeAlias type="demo.mybatis.entity.User" alias="user"/>
</typeAliases>
<select id="findUsers" resultType="user">
select id, user_code userCode, user_name userName,sex, brithday from sy_user
</select>
----------------------------------------------------------------
类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简单类名小写。
<typeAliases>
<package name="demo.mybatis.entity"/>
</typeAliases>
-----------------------------------------------------------------
也可以使用@Alias注解为其指定一个别名--- 无效
@Alias("User2")
public class User {
5.4、typeHandlers类型处理器
- 无论是 MyBatis 在预处理语句(PreparedStatement)中 设置一个参数时,
- 还是从结果集中取出一个值时, 都会**用类型处理器将获取的值以合适的方式转换成 Java 类型。
5.4.1、系统自带预处理
| 类型处理器 | Java 类型 | JDBC 类型 |
|---|---|---|
BooleanTypeHandler |
java.lang.Boolean, boolean |
数据库兼容的 BOOLEAN |
ByteTypeHandler |
java.lang.Byte, byte |
数据库兼容的 NUMERIC 或 BYTE |
ShortTypeHandler |
java.lang.Short, short |
数据库兼容的 NUMERIC 或 SHORT INTEGER |
IntegerTypeHandler |
java.lang.Integer, int |
数据库兼容的 NUMERIC 或 INTEGER |
LongTypeHandler |
java.lang.Long, long |
数据库兼容的 NUMERIC 或 LONG INTEGER |
FloatTypeHandler |
java.lang.Float, float |
数据库兼容的 NUMERIC 或 FLOAT |
DoubleTypeHandler |
java.lang.Double, double |
数据库兼容的 NUMERIC 或 DOUBLE |
BigDecimalTypeHandler |
java.math.BigDecimal |
数据库兼容的 NUMERIC 或 DECIMAL |
StringTypeHandler |
java.lang.String |
CHAR, VARCHAR |
ClobReaderTypeHandler |
java.io.Reader |
- |
ClobTypeHandler |
java.lang.String |
CLOB, LONGVARCHAR |
NStringTypeHandler |
java.lang.String |
NVARCHAR, NCHAR |
NClobTypeHandler |
java.lang.String |
NCLOB |
BlobInputStreamTypeHandler |
java.io.InputStream |
- |
ByteArrayTypeHandler |
byte[] |
数据库兼容的字节流类型 |
BlobTypeHandler |
byte[] |
BLOB, LONGVARBINARY |
DateTypeHandler |
java.util.Date |
TIMESTAMP |
DateOnlyTypeHandler |
java.util.Date |
DATE |
TimeOnlyTypeHandler |
java.util.Date |
TIME |
SqlTimestampTypeHandler |
java.sql.Timestamp |
TIMESTAMP |
SqlDateTypeHandler |
java.sql.Date |
DATE |
SqlTimeTypeHandler |
java.sql.Time |
TIME |
ObjectTypeHandler |
Any | OTHER 或未指定类型 |
EnumTypeHandler |
Enumeration Type | VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引) |
EnumOrdinalTypeHandler |
Enumeration Type | 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。 |
5.4.2、日期类型处理
- 日期和时间的处理,JDK1.8以前一直是个头疼的 问题。我们通常使用JSR310规范领导者Stephen Colebourne创建的Joda-Time来操作。1.8已经实 现全部的JSR310规范了。
- 日期时间处理上,我们可以使用MyBatis基于 JSR310(Date and Time API)编写的各种日期 时间类型处理器。
- MyBatis3.4以前的版本需要我们手动注册这些处 理器,以后的版本都是自动注册的Type Handlers for JSR 310: Date and Time API
- JDK8,新特性,时间的处理。类型处理器。
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.InstantTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.LocalDateTimeTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.LocalDateTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.LocalTimeTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.OffsetDateTimeTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.OffsetTimeTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.ZonedDateTimeTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.YearTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.MonthTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.YearMonthTypeHandler" />
<typeHandler handler="org.apache.ibatis.type.JapaneseDateTypeHandler" />
</typeHandlers>
5.4.3、自定义类型处理器
- 我们可以重写类型处理器或创建自己的类型处理器来处理不支持的或非标准的类型。
- 步骤:
- 1)、实现org.apache.ibatis.type.TypeHandler接口或者继承org.apache.ibatis.type.BaseTypeHandler
- 2)、指定其映射某个JDBC类型(可选操作)
- 3)、在mybatis全局配置文件中注册
5.5、objectFactory 对象工厂(略)
5.6、plugins 插件
插件是MyBatis提供的一个非常强大的机制,我们可以通过插件来修改MyBatis的一些核心行为。插件通过动态代理机制,可以介入四大对象的任何一个方法的执行。
- Executor (update, query, flushStatements, commit, rollback,getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
5.7、environments 环境
- MyBatis可以配置多种环境,比如开发、测试和生 产环境需要有不同的配置。
- 每种环境使用一个environment标签进行配置并指 定唯一标识符
- 可以通过environments标签中的default属性指定 一个环境的标识符来快速的切换环境
<!-- environments 是配置多个jdbc环境
default表示使用的默认环境 -->
<environments default="development">
<!-- environment 标签用来配置一个环境
id 是环境的标识 -->
<environment id="development">
<!--transactionManager 配置使用什么样类型的数据库事务管理
type="JDBC" 表示启用事务,有commit和rollback操作
type="MANAGED" 表示不直接控制事务。交给容器处理 - 几乎不用。 -->
<transactionManager type="JDBC"/>
<!-- dataSource标签配置连接池
type="POOLED" 表示启用数据库连接池
type="UNPOOLED" 表示不启用数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/> <!-- 连接数据库的驱动类 -->
<property name="url" value="${jdbc.url}"/> <!-- 数据库访问地址 -->
<property name="username" value="${jdbc.user}"/> <!-- 数据库用户名 -->
<property name="password" value="${jdbc.password}"/> <!-- 数据库密码 -->
</dataSource>
</environment>
</environments>
id :
- 指定当前环境的唯一标识
transactionManager:
type: JDBC | MANAGED | 自定义
- JDBC:使用了 JDBC 的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围。JdbcTransactionFactory
- MANAGED:不提交或回滚一个连接、让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 ManagedTransactionFactory
- 自定义:实现TransactionFactory接口,type=全类名/别名
dataSource
type: UNPOOLED | POOLED | JNDI | 自定义
- UNPOOLED:不使用连接池,UnpooledDataSourceFactory
- POOLED:使用连接池, PooledDataSourceFactory
- JNDI: 在EJB 或应用服务器这类容器中查找指定的数据源
- 自定义:实现DataSourceFactory接口,定义数据源的获取方式。
实际开发中我们使用Spring管理数据源,并进行 事务控制的配置来覆盖上述配置
5.8、databaseIdProvider环境
MyBatis 可以根据不同的数据库厂商执行不同的语句。
Type: DB_VENDOR
- 使用MyBatis提供的 VendorDatabaseIdProvider 解析数据库 厂商标识。也可以实现DatabaseIdProvider接口来自定义。
- 会通过 DatabaseMetaData#getDatabaseProductName() 返回的字符串进行设置。由于通常情况下这个字符串都非常长而且相同产品的不同版本会返回不同的值,所以最好通过设置属性别名来使其变短
Property-name:数据库厂商标识
Property-value:为标识起一个别名,方便SQL语句使用 databaseId属性引用
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver" />
<property name="MySQL" value="mysql" />
<property name="DB2" value="db2" />
<property name="Oracle" value="oracle" />
</databaseIdProvider>
<select id="selectUserById" parameterType="int" resultType="user" databaseId="mysql">
select id , user_code from sy_user where id = #{value}
</select>
MyBatis匹配规则如下:
- 1、如果没有配置databaseIdProvider标签,那么databaseId=null
- 2、如果配置了databaseIdProvider标签,使用标签配置的name去匹 配数据库信息,匹配上设置databaseId=配置指定的值,否则依旧为 null
- 3、如果databaseId不为null,他只会找到配置databaseId的sql语句
- 4、MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。
5.9、Mappers 映射器
把mapper配置文件注入到mybatis-config.xml核心配置文件中有三种常用方式。
- 1、在classpath路径下引入
- 2、使用mapper接口的形式导入配置
- 3、使用包扫描的方式引入配置文件
<!-- 扫描包下所有的配置文件
1、接口名和Mapper配置文件名必须相同
2、接口文件和Mapper配置文件必须在同一个包下 -->
<mappers>
<!-- <mapper resource="mapper/UserMapper.xml"/>-->
<!-- <mapper url="file:///D:\Develop\WorkSpace\work_01\Demo\MyBatis\src\main\resources\mapper\UserMapper.xml"/>-->
<!-- <mapper class="demo.mybatis.dao.UserDao"/> <!–通常用于注解模式 –>-->
<package name="demo.mybatis.dao"/> <!-- 需要跟 mapper.xml 在同一个目录下 -->
</mappers>
6、注解
6.1、配置mybatis-config.xml
<mappers>
<mapper class="demo.mybatis.dao.UserDaoAnnotation"/> <!--通常用于注解模式 -->
</mappers>
6.2、编写Dao接口
package demo.mybatis.dao;
import demo.mybatis.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserDaoAnnotation {
@Select("select id,user_name userName ,sex from sy_user where id = #{id}")
public User selectUser(int id);
@Select("select * from sy_user")
public List<User> selectUserList();
@Update("update sy_user set user_name = #{userName}, sex = #{sex} where id = #{id}")
public int updateUser(User user);
@Delete("delete from sy_user where id = #{id}")
public int deleteUserById(int id);
@Insert("insert into sy_user(`user_name`,`sex`) values(#{userName},#{sex})")
@SelectKey(before = false, keyProperty = "id", resultType = Integer.class, statement = {"select last_insert_id()"})
public int saveUser_selectKey(User user);
@Insert("insert into sy_user(`user_name`,`sex`) values(#{userName},#{sex})")
public int saveUser(User user);
}
6.3、单元测试
package demo.mybatis;
import demo.mybatis.dao.UserDao;
import demo.mybatis.dao.UserDaoAnnotation;
import demo.mybatis.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
public class Test05 {
UserDaoAnnotation userDaoAnnotation;
SqlSession session;
@Before
public void setUpBeforeClass() throws Exception {
String url = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(url);
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
userDaoAnnotation = session.getMapper(UserDaoAnnotation.class);
}
@Test
public void testSaveUser() {
User user = new User();
user.setSex("女");
user.setUserCode("0003");
user.setUserName("花木兰");
user.setBrithday(new Date());
System.out.println(userDaoAnnotation.saveUser(user));
System.out.println(user);
session.commit();
}
@Test
public void testUpdateUser() {
User user = new User();
user.setId(1);
user.setSex("女");
user.setUserCode("0004");
user.setUserName("花木兰2");
user.setBrithday(new Date());
userDaoAnnotation.updateUser(user);
System.out.println(user);
session.commit();
}
@Test
public void testDeleteUserById() {
System.out.println("更新条数:" + userDaoAnnotation.deleteUserById(2));
session.commit();
}
@Test
public void testFindUserById() {
System.out.println(userDaoAnnotation.selectUser(1));
}
@Test
public void testFindUsers() {
System.out.println(userDaoAnnotation.selectUserList());
}
}
7、Mapper.xml映射
7.1、插入返回主键
7.1.1、编写UserDao
// 保存用户
public int saveUser_getKey(User user);
// 保存用户
public int saveUser_selectKey(User user);
8.1.2、编写UserMapper.xml
<!-- 插入用户
useGeneratedKeys="true"
表示返回生成的主键
keyProperty 表示把返回的key注入到返回值的哪个属性中
keyProperty="id" 表示把返回的id主键值注入到返回对象的id属性中
-->
<insert id="saveUser_getKey" useGeneratedKeys="true" keyProperty="id" parameterType="demo.mybatis.entity.User">
insert into sy_user(user_code , user_name ,sex,brithday) values(#{userCode},#{userName},#{sex},#{brithday})
</insert>
<!--
selectKey标签主要用于插入数据后,获取生成的主键。
order 表示执行的顺序,AFTER表示在插入之后执行。BEFORE在插入之前执行。
keyProperty属性设置对象的哪个属性接收
resultType属性设置返回值类型。
oracle则使用以下方式
selectKey 返回Oracle的序列自增主键
<selectKey order="BEFORE" resultType="int" keyProperty="id">
select 序列名.nextval as id from dual
</selectKey>
-->
<insert id="saveUser_selectKey" parameterType="demo.mybatis.entity.User">
<selectKey order="AFTER" keyProperty="id" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
insert into sy_user(user_code , user_name ,sex,brithday) values(#{userCode},#{userName},#{sex},#{brithday})
</insert>
7.1.3、单元测试
package demo.mybatis;
import demo.mybatis.dao.UserDao;
import demo.mybatis.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
/**
* 插入返回主键演示
*/
public class Test04 {
UserDao userDao;
SqlSession session;
@Before
public void setUpBeforeClass() throws Exception {
String url = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(url);
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
userDao = session.getMapper(UserDao.class);
}
@Test
public void testSaveUserGetKey() {
User user = new User();
user.setSex("女");
user.setUserCode("0003");
user.setUserName("花木兰");
user.setBrithday(new Date());
System.out.println(userDao.saveUser_getKey(user));
System.out.println(user);
session.commit();
}
@Test
public void testSaveUserSelectKey() {
User user = new User();
user.setSex("女");
user.setUserCode("0003");
user.setUserName("花木兰");
user.setBrithday(new Date());
System.out.println(userDao.saveUser_selectKey(user));
System.out.println(user);
session.commit();
}
}
7.2、参数传递
单个参数
- 可以接受基本类型,对象类型,集合类型的值。这种情况 MyBatis可直接使用这个参数,不需要经过任何处理。
多个参数
- 任意多个参数,都会被MyBatis重新包装成一个Map传入。 Map的key是param1,param2,0,1…,值就是参数的值。
POJO
- 当这些参数属于我们业务POJO时,我们直接传递POJO
多个POJO
Map
- 我们也可以封装多个参数为map,直接传递
7.2.1、单个参数
- 当一个方法中只有一个普通数据类型。在mapper配置文件中可以使用#{}占位符来进行占位输出。
- #{} 占位符中,可以写参数的 #{变量名}。 也可以写 #{value}。
方法: public int deleteUserById(int id);
-- #{变量名}
<delete id="deleteUserById" parameterType="int">
delete from sy_user where id = #{id}
</delete>
-- #{value}
<delete id="deleteUserById" parameterType="int">
delete from sy_user where id = #{value}
</delete>
7.2.2、多个参数
- 1、多个普通的参数。当我们需要使用 #{} 占位输出的时候,可以使用param1,param2 …… paramN 也就是 #{param1} …… #
- 2、使用@Param命名参数
方法1: public List<User> findUserByNameAndSex(String username, int sex);
<select id="findUserByNameAndSex" resultType="demo.mybatis.entity.User" >
select id,user_name userName,sex from sy_user where user_name = #{param1} and sex = #{param2}
</select>
--------------------------------
方法2:public List<User> findUserByNameAndSex(@Param("username") String username, @Param("sex") int sex);
<select id="findUserByNameAndSex" resultType="demo.mybatis.entity.User" >
select id,user_name userName,sex from sy_user where user_name = #{lastName} and sex = #{sex}
</select>
8.2.3、单个POJO
- 当方法的参数是一个复杂类型的对象的时候。我们可以使用 对象的属性名。当成占位符的名称。比如:#
示例: public int insertUser(User user);
<insert id="insertUser" parameterType="demo.mybatis.entity.User" useGeneratedKeys="true" keyProperty="id">
insert into sy_user(`user_name`,`sex`) values(#{userName},#{sex})
</insert>
7.2.4、多个POJO
- 当有多个复杂pojo对象做为参数传递给方法使用时候。我们要取出数据做为sql的参数。可以使用如下方式:#{param1.属性名}……#
- 也可以使用@Param命名参数。给每个pojo对象起一个别名。然后再通过 #{别名.属性名} 的方式取出数据值做为参数使用。
默认param1、param2、paramN形式取对象属性。
方法:public List<User> findUserByTwoUser(User user1, User user2);
<select id="findUserByTwoUser" resultType="demo.mybatis.entity.User" >
select id,user_name userName,sex from sy_user where user_name = #{param1.userName} and sex = #{param2.sex}
</select>
----------------------------------------------
@Param注解命名参数的形式
方法:public List<User> findUserByTwoUser(@Param("user1") User user1, @Param("user2") User user2);
<select id="findUserByTwoUser" resultType="demo.mybatis.entity.User" >
select id,user_name userName,sex from sy_user where user_name = #{user1.userName} and sex = #{user2.sex}
</select>
7.2.5、Map对象
- 当我们的参数为map对象的时候。我们可以使用 map对象的key来做为占位符,输出数据。#{map的key} 来做为占位符的输出
方法:public List<User> findUserByMap(Map<String, Object> map);
<select id="findUserByMap" resultType="demo.mybatis.entity.User" >
select id,user_name userName,sex from user_name where user_name = #{userName} and sex = #{sex}
</select>
@Test
public void findUserByMap() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
Map<String, Object>map = new HashMap<String, Object>();
map.put("userName", "admin");
map.put("sex", 1);
System.out.println( userMapper.findUserByMap(map) );
} finally {
session.close();
}
}
7.3、模糊查询
- 现在要根据用户名查询用户对象。即查询: select * from t_user where user_name like '%张%'
7.3.1、使用 #{}
方法:public List<User> findUserLikeName(String name);
<select id="findUserLikeName" resultType="demo.mybatis.entity.User" >
select id,user_name userName ,sex from t_user where user_name like #{userName}
</select>
@Test
public void findUserLikeName() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
// 需要在传递参数的时候,自己加上前后的两个百分号
System.out.println( userMapper.findUserLikeName("%a%") );
} finally {
session.close();
}
}
7.3.2、使用${}
方法:public List<User> findUserLikeName(String name);
<select id="findUserLikeName" resultType="user" >
select id,user_name userName ,sex,phone from t_user where user_name like '%${value}%'
</select>
@Test
public void findUserLikeName() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
// 需要在传递参数的时候,自己加上前后的两个百分号
System.out.println( userMapper.findUserLikeName("a") );
} finally {
session.close();
}
}
7.3.3、使用concat函数拼接
方法:public List<User> findUserLikeName(String name);
<select id="findUserLikeName" resultType="user" >
select id,user_name userName ,sex from t_user where user_name like concat('%',#{name},'%');
</select>
@Test
public void findUserLikeName() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
// 需要在传递参数的时候,自己加上前后的两个百分号
System.out.println( userMapper.findUserLikeName("a") );
} finally {
session.close();
}
}
7.4、#{}和${}的区别
- #{} 在mapper的配置文件的sql语句中,它是占位符, 相当于 ? 号。
- ${} 在 mapper 的配置文件的 sql 语句中,它是原样输出变量的值,然后以字符串拼接的功能进行操作。
- ${} 中只能写value,或者是@Param命名参数后的参数名称
- 在输出参数的时候,我们并不推荐使用 ${} 来输出。因为可能会导至 sql 注入问题的存在
比如:select * form sy_user where id = #{id}
相当于:select * from t_user where id = ?
而select * from sy_user where id = ${value}
相当于select * from t_user where id = 原样输出变量的值
8、自定义结果集
ResultMap标签可以给那些查询出来的结果要封装成为的Bean对象。是复杂bean对象的情况。
原来我们查询出来的结果,封装的对象里面的属性都是普通的属性。不包含子的javaBean对象。也不包含Bean对象的集合。那种叫普通的javabean。
那些Bean对象中又包含了子的Bean对象的情况,或者是Bean对象中又包含的bean对象集合的情况,叫复杂的Bean对象。
这种情况,只能使用ResultMap标签来将结果集转换成为复杂的Bean对象。而简单的不需要。简单的Bean对象,只需要使用ResultType属性即可。
8.1、实例演示
8.1.1、数据准备
## 一对一数据表
## 创建锁表
create table t_lock(
`id` int primary key auto_increment,
`name` varchar(50)
);
## 创建钥匙表
create table t_key(
`id` int primary key auto_increment,
`name` varchar(50),
`lock_id` int ,
foreign key(`lock_id`) references t_lock(`id`)
);
## 插入初始化数据
insert into t_lock(`name`) values('锁1');
insert into t_lock(`name`) values('锁2');
insert into t_lock(`name`) values('锁3');
insert into t_key(`name`,`lock_id`) values('钥匙1',1);
insert into t_key(`name`,`lock_id`) values('钥匙2',2);
insert into t_key(`name`,`lock_id`) values('钥匙3',3);
8.1.2、创建实体
钥匙对象
public class Key {
private int id;
private String name;
private Lock lock;
锁对象
public class Lock {
private int id;
private String name;
8.1.3、编写Mapper映射
<?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="demo.mybatis.dao.KeyMapper">
<!--
resultMap标签专门用来定义自定义的结果集数据。
type属性设置返回的数据类型
id属性定义一个唯一标识
-->
<resultMap type="demo.mybatis.entity.Key" id="queryKeyForSimple_resultMap">
<!-- id定义主键列 -->
<id column="id" property="id"/>
<!-- result 定义一个列和属性的映射 -->
<result column="name" property="name"/>
<!-- <!– lock.id 和 lock.name 叫级联属性映射 –>-->
<!-- <result column="lock_id" property="lock.id"/>-->
<!-- <result column="lock_name" property="lock.name"/>-->
<!--
association 标签可以给一个子对象定义列的映射。
property 属性设置 子对象的属性名 lock
javaType 属性设置子对象的全类名
-->
<association property="lock" javaType="demo.mybatis.entity.Lock">
<!-- id 属性定义主键 -->
<id column="lock_id" property="id"/>
<!-- result 标签定义列和对象属性的映射 -->
<result column="lock_name" property="name"/>
</association>
</resultMap>
<!--
select 标签用于定义一个select语句
id属性设置一个statement标识
parameterType设置参数的类型
resultMap 设置返回的结果类型
-->
<select id="queryKeyForSimple" parameterType="int" resultMap="queryKeyForSimple_resultMap">
select t_key.*,t_lock.name lock_name
from
t_key left join t_lock
on
t_key.lock_id = t_lock.id
where
t_key.id = #{id}
</select>
</mapper>
8.1.4、单元测试
package demo.mybatis;
import demo.mybatis.dao.KeyMapper;
import demo.mybatis.dao.UserDaoAnnotation;
import demo.mybatis.entity.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
public class Test06 {
KeyMapper keyMapper;
SqlSession session;
@Before
public void setUpBeforeClass() throws Exception {
String url = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(url);
// 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
keyMapper = session.getMapper(KeyMapper.class);
}
@Test
public void testSaveUser() {
System.out.println( keyMapper.queryKeyForSimple(1) );
}
}
浙公网安备 33010602011771号