这篇文章主要介绍“MyBatis简单使用实例”,在日常操作中,相信很多人在MyBatis简单使用实例问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MyBatis简单使用实例”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
使用MyBatis可以分以下几个关键点
引入MyBatis依赖
配置mybatis-config.xml配置文件
创建数据库实体类与Mapper映射文件
通过SqlSessionFactoryBuilder加载配置并使用
以下按步骤写一个单元测试:
引入依赖
<!-- mybatis依赖包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!-- 数据库驱动 需要使用 5.1.40以上才可解决mysql json格式乱码问题 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
</dependency>
编写配置文件
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="db.properties"></properties>
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 控制全局缓存(二级缓存),默认 true-->
<setting name="cacheEnabled" value="false"/>
<!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false -->
<setting name="lazyLoadingEnabled" value="false"/>
<!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<!--<setting name="proxyFactory" value="CGLIB" />-->
<!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效,相当于关闭一级缓存 -->
<!--
<setting name="localCacheScope" value="STATEMENT"/>
-->
<setting name="localCacheScope" value="SESSION"/>
</settings>
<typeAliases>
<typeAlias alias="user" type="com.freecloud.plug.mybatis.entity.User" />
<typeAlias alias="myBatisJson" type="com.freecloud.plug.mybatis.entity.MyBatisJson" />
<typeAlias alias="department" type="com.freecloud.plug.mybatis.entity.Department" />
<typeAlias alias="userAndDepartment" type="com.freecloud.plug.mybatis.entity.UserAndDepartment" ></typeAlias>
</typeAliases>
<!-- 自定义类型转换器 -->
<typeHandlers>
<typeHandler handler="com.freecloud.plug.mybatis.type.JsonTypeHandler"></typeHandler>
</typeHandlers>
<plugins>
<plugin interceptor="com.freecloud.plug.mybatis.plugins.SQLExecuteTimeInterceptor">
<property name="name" value="zhangsan" />
</plugin>
<plugin interceptor="com.freecloud.plug.mybatis.plugins.SimpleTableInterceptor"></plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<mapper resource="mapper/MyBatisJsonMapper.xml"/>
<mapper resource="mapper/DepartmentMapper.xml"/>
</mappers>
</configuration>
db.properties数据库连接配置
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/data_test?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true
jdbc.username=root
jdbc.password=123456
初始化数据,用于后边的单元测试。
## 部门表
CREATE TABLE `department` (
`id` int(5) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`parent_id` int(5) NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
## 员工表
CREATE TABLE `user_department` (
`id` int(5) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`age` int(4) DEFAULT NULL,
`default_department_id` int(5) NOT NULL,
`all_department_id` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
## 初始化部门
insert into department values (1,'部门1',null);
insert into department values (2,'部门2',1);
insert into department values (3,'部门3',null);
## 初始化员工
insert into user_department values (1,'张三',18,1,'2,3');
insert into user_department values (2,'李4',18,2,'1,2');
insert into user_department values (3,'王5',18,3,'3');
insert into user_department values (4,'赵6',18,1,'1');
数据库实体类与mapper配置
/**
* 业务实体对象
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
/** 主键ID */
private Long id;
/** 姓名 */
private String name;
/** 年龄 */
private Integer age;
}
UserMapper.xml 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.freecloud.plug.mybatis.dao.UserMapper">
<!-- 声明这个namespace使用二级缓存 -->
<!-- <cache/>-->
<!-- 使用Redis作为二级缓存 -->
<!--
<cache type="org.mybatis.caches.redis.RedisCache"
eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
-->
<cache type="org.apache.ibatis.cache.impl.PerpetualCache"
size="1024"
eviction="LRU"
flushInterval="120000"
readOnly="false"/>
<resultMap id="BaseResultMap" type="user">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="INTEGER"/>
</resultMap>
<!-- 对象关联查询,一条sql直接查询 -->
<resultMap id="UserAndDepartmentResultMap" type="userAndDepartment">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="INTEGER"/>
<association property="defaultDepartment" javaType="com.freecloud.plug.mybatis.entity.Department" >
<id column="department_id" property="id"></id>
<result column="department_name" property="name" ></result>
</association>
</resultMap>
<!-- 联合查询,会产生 N+1的问题 -->
<resultMap id="UserAndDepartmentResultMap1" type="userAndDepartment">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="INTEGER"/>
<!-- 此处可以夸namespace调用,但要保证当前应用加载对应mapper -->
<association property="defaultDepartment" column="default_department_id"
javaType="com.freecloud.plug.mybatis.entity.Department"
select="com.freecloud.plug.mybatis.dao.DepartmentMapper.byId" ></association>
</resultMap>
<!-- 联合查询,一对多 -->
<resultMap id="UserAndDepartmentResultMap2" type="userAndDepartment">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="INTEGER"/>
<!-- 此处可以夸namespace调用,但要保证当前应用加载对应mapper -->
<!-- <association property="defaultDepartment" column="default_department_id"-->
<!-- javaType="com.freecloud.plug.mybatis.entity.Department"-->
<!-- select="com.freecloud.plug.mybatis.dao.DepartmentMapper.byId" ></association>-->
<collection property="departmentList" column="all_department_id"
ofType="com.freecloud.plug.mybatis.entity.Department"
select="com.freecloud.plug.mybatis.dao.DepartmentMapper.byIds"></collection>
</resultMap>
<select id="byId" resultMap="BaseResultMap" statementType="PREPARED" >
select * from user_department where id = #{id}
</select>
<insert id="save" parameterType="user" >
insert into user_department (id,name,age)
values (#{id},#{name},#{age})
</insert>
<update id="update" parameterType="user">
update user_department
<set>
<if test="name != null">
name = #{name}
</if>
<if test="age != null">
,age = #{age}
</if>
</set>
where id = #{id}
</update>
<select id="getUserAndDepartmentById" parameterType="long" resultMap="UserAndDepartmentResultMap" >
select a.id,a.name,a.age,b.id as department_id,b.name as department_name
from user_department a
left join department b
on a.default_department_id = b.id
where a.id = #{id}
</select>
<select id="getUserAndDepartmentById1" parameterType="long" resultMap="UserAndDepartmentResultMap1" >
select *
from user_department a
where a.id = #{id}
</select>
<select id="getUserAndDepartmentById2" parameterType="long" resultMap="UserAndDepartmentResultMap2" >
select *
from user_department a
where a.id = #{id}
</select>
</mapper>
mapper调用接口,方法名要到Mapper.xml文件中的配置的Id相同,否则无法映射成功。
public interface UserMapper {
/**
* 根据主键查询
* @param id
* @return
*/
public User byId(Long id);
/**
* 新增
* @param user
* @return
*/
public void save(User user);
/**
* 修改
* @param user
*/
public void update(User user);
/**
* 多表关联查询
* @param id
* @return
*/
public UserAndDepartment getUserAndDepartmentById(Long id);
/**
* 关联查询,有N + 1问题
* @param id
* @return
*/
public UserAndDepartment getUserAndDepartmentById1(Long id);
/**
* 关联查询,1对多
* @param id
* @return
*/
public UserAndDepartment getUserAndDepartmentById2(Long id);
}
单元测试
package com.freecloud.plug.mybatis;
import com.freecloud.common.LoggerUtil;
import com.freecloud.plug.mybatis.dao.UserMapper;
import com.freecloud.plug.mybatis.entity.User;
import com.freecloud.plug.mybatis.entity.UserAndDepartment;
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;
/**
* @Author: maomao
* @Date: 2021-04-08 11:36
*/
public class MyBatisTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
/**
* 使用mybatis api 方式硬编码方式
*/
@Test
public void testApiStatement(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
sqlSession.selectOne("com.freecloud.plug.mybatis.dao.UserMapper.byId",1);
}finally {
sqlSession.close();
}
}
/**
* 测试使用mapper包装直接使用接口调用
*/
@Test
public void testMapperInterface(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.byId(1L);
LoggerUtil.printThread(user.toString());
}finally {
sqlSession.close();
}
}
/**
* 多表关联查询
*/
@Test
public void testUserAndDepartment(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserAndDepartment user = userMapper.getUserAndDepartmentById(1L);
LoggerUtil.printThread(user.toString());
}finally {
sqlSession.close();
}
}
/**
* 关联查询,有N + 1问题
*/
@Test
public void testUserAndDepartment1(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserAndDepartment user = userMapper.getUserAndDepartmentById1(1L);
LoggerUtil.printThread(user.toString());
}finally {
sqlSession.close();
}
}
/**
* 关联查询,1对多
*/
@Test
public void testUserAndDepartment2(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserAndDepartment user = userMapper.getUserAndDepartmentById2(1L);
LoggerUtil.printThread(user.toString());
}finally {
sqlSession.close();
}
}
}
使用以上例子,就可以运行起来MyBatis。看单元测试中的使用方法,分别描述了几种常见方式。
使用传统硬编码直接通过Mapper映射器中配置的ID访问
使用一个空接口实现方法调用(无实现类),使用sqlSession.getMapper(UserMapper.class);方式获取实例执行
对象关联性查询一对多、一对一形式
在单元测试类中我们看到了MyBatis里面的几个核心对象:
SqlSessionFactoryBuiler
SqlSessionFactory
SqlSession
Mpper
这几个核心对象在MyBatis的整个工作流程里面的不同环节发挥作用。如果我们不用容器,自己去管理这些对象的话,我们必须考虑一个问题:什么时候创建和销毁这些对象?
在一些分布式应用里,多线程高并发场景中,如果要写出高效的代码,就必须了解这四个对象的生命周期。
它是用来构建SqlSessionFactory与解析mybatis-config等配置的,而SqlSessionFactory只需要一个,所以只要构建了一个SqlSessionFactory之后它的使命就完成了,也就没有存在的必要了。所以它的生命周期只存在于方法的局部。
SqlSessionFactory是用来创建SqlSession的,每次访问数据库都需要创建一个回话。因为我们一直有创建会话的需要,所以SqlSessionFactory应该存在于应用的整个生命周期中(作用域是应用作用域)。创建SqlSession只需要一个实例来做这件事就可以了,否则会造成混乱和资源浪费。所以我们应该采用单例模式。
一般工厂类在都应该是单例模式。
SqlSession是一个会话,因为它不是线程安全的,不能在线程间共享。所以我们在请求开始的时候创建一个SqlSession对象,在请求结束时要及时关闭它。也可以把它理解成Jdbc 的Connection连接。
实际是Mapper是一个代理对象,是从SqlSession中获取的。
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
它的作用是发送Sql来操作数据库的数据。它应该在一个SqlSession事务方法之内。
对象 | 作用域 |
---|---|
SqlSessionFactoryBuilder | 方法局部(method) |
SqlSessionFactory | 应用级别(application) |
SqlSession | 请求和操作(request、method) |
Mapper | 方法(method) |
以上就是四个核心对象的生命周期。
到此,关于“MyBatis简单使用实例”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/1019754/blog/5016075