ps:好吧,起这个名字就是引起你的注意,哈哈。
写这篇博文,主要是想温故知新,在回顾的同时,希望可以看到一些新的点;希望可以帮到你,如果有新的发现的话,还请点个赞。先上MyBatis官网地址:www.mybatis.org/mybatis-3/
一句话介绍MyBatis
MyBatis是一款优秀的基于ORM的半自动轻量级持久层框架。抓取关键字:基于ORM、半自动、轻量级、持久化,接下来一一解释。
基于ORM
何为ORM? ORM即Object Relational Mapping,对象关系映射,ORM完成了对象到数据库的映射。可以理解为程序对象和数据库中表之间的桥梁,ORM框架将面向对象的操作转化为了对数据库中表的操作,大大提高了开发效率。
半自动
有半自动化,就有自动化。全自动化框架比较典型的就是Hibernate,它无需手写SQL,直接操作对象即可,好处是大大降低了对象与数据库的耦合性,可移植性好,但是面对复杂业务,实现及优化困难;Mybatis需要手写SQL,更加灵活,可以使后端代码与SQL功能分离,边界清晰,但是可移植性差,做过数据库迁移的都懂哈。
轻量级
重量级的框架,在启动的时候需要消耗大量的资源,内存,CPU等,比如EJB,本身也有120M;而轻量级框架,比如我们讲的Mybatis,在启动时消耗的资源就少很多,自身也只有不到3M。
持久化
持久化,顾名思义,就是对持久层进行操作,将对象永久的保存在数据库中。
快速入门
上文了解了MyBatis的基本信息,现在开始准备第一个简单的demo。
准备张表
CREATE TABLE `t_company` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(50) DEFAULT NULL COMMENT '公司名',
`region` varchar(50) DEFAULT NULL COMMENT '地域',
`boss` varchar(50) DEFAULT NULL COMMENT '老板',
`creator` varchar(50) DEFAULT NULL COMMENT '创建者',
`create_tm` timestamp DEFAULT NULL COMMENT '创建时间',
`updater` varchar(50) DEFAULT NULL COMMENT '修改者',
`update_tm` timestamp DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=81 DEFAULT CHARSET=utf8 COMMENT='公司'
创建springboot项目
创建一个springboot项目,并引入以下依赖
<dependency>
<!--这是由mybatis提供的第三方starter,spring并未提供与mybatis整合的starter。后续我们也可以写个自己的starter-->
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
添加连接数据库相关配置信息,填写自己所连数据库信息
#数据库连接配置信息
spring.datasource.url=jdbc:mysql://****
spring.datasource.username=****
spring.datasource.password=****
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
创建公司表的实体类
@Data
public class CompanyVO {
/**
* id
*/
private int id;
/**
* 名称
*/
private String name;
/**
* 区域
*/
private String region;
/**
* 老板
*/
private String boss;
/**
* 创建人
*/
private String creator;
/**
* 创建时间
*/
private Date create_tm;
/**
* 更新人
*/
private String updater;
/**
* 更新时间
*/
private String update_tm;
}
创建mapper类
@Mapper
public interface CompanyMapper {
/**
* 根据ID查询
* @param id
* @return
*/
CompanyVO selectById(Integer id);
/**
* 插入一条数据
* @param companyVO
*/
void insertOne(CompanyVO companyVO);
}
创建mapper.xml,mapper建在resource目录下,路径需要和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="com.example.demo.company.mapper.CompanyMapper">
<resultMap id="BaseResultMap" type="com.example.demo.company.vo.CompanyVO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="region" jdbcType="VARCHAR" property="region" />
<result column="boss" jdbcType="VARCHAR" property="boss" />
<result column="creator" jdbcType="VARCHAR" property="creator" />
<result column="create_tm" jdbcType="TIMESTAMP" property="createTm" />
<result column="updater" jdbcType="VARCHAR" property="updater" />
<result column="update_tm" jdbcType="TIMESTAMP" property="updateTm" />
</resultMap>
<!--根据ID查询-->
<select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
SELECT * FROM t_company
WHERE id=#{id}
</select>
<!--插入数据-->
<insert id="insertOne" parameterType="com.example.demo.company.vo.CompanyVO">
INSERT INTO t_company
(name, region, boss, creator,
create_tm, updater, update_tm
)
VALUES
( #{name}, #{region}, #{boss},
#{creator}, #{createTm}, #{updater}, #{updateTm})
</insert>
</mapper>
创建service类
@Service
public class CompanyService {
/**
* mapper
*/
@Autowired
private CompanyMapper companyMapper;
/**
* 根据ID查询
* @param id
* @return
*/
public CompanyVO selectById(Integer id){
return companyMapper.selectById(id);
}
/**
* 插入一条
* @param companyVO
*/
public void insertOne(CompanyVO companyVO){
companyMapper.insertOne(companyVO);
}
}
创建测试类,进行测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test {
@Autowired
private CompanyService service;
/**
* selectById
*/
@org.junit.Test
public void selectById(){
CompanyVO companyVO = service.selectById(1);
System.out.println(companyVO.toString());
}
/**
* 插入一条数据
*/
@org.junit.Test
public void insertOne(){
CompanyVO companyVO = new CompanyVO();
companyVO.setBoss("东哥");
companyVO.setName("京东");
companyVO.setRegion("北京");
companyVO.setRegion("北京");
companyVO.setCreator("anyu~");
companyVO.setCreateTm(DateUtil.now());
companyVO.setUpdater("anyu~");
companyVO.setUpdateTm(DateUtil.now());
service.insertOne(companyVO);
}
}
执行测试类,为了方便查看执行的SQL语句,可以在配置文件中,加入下面配置
#日志打印
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
执行插入,查看日志
插入后,数据库查一下
执行查询,查看日志
自定义插件
上面的demo中,创建时间和修改时间、创建人和修改人,每次都需要set,一点儿也不优雅,对于这种和业务无关每个表还需要的字段,有没有方法自动加上呢?当然有,我们可以自定义一个插件,自动去做。
MyBatis插件机制介绍
一般情况下,开源框架都会提供插件机制,供我们灵活拓展。显而易见,这样不仅增加了框架的灵活性,而且还可以结合实际需求,拓展定制化的功能,更好的完成开发工作。MyBatis作为一个优秀的ORM开源框架,也提供了相关组件,供我们灵活扩展。四大核心对象分别是
Executor:SQL执行器,完成对数据库的增删改查操作;允许拦截的方法包括(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
StatementHandler:封装了对JDBC Statement对象的操作,执行SQL语句,实现与数据库的交互;允许拦截的方法包括(prepare, parameterize, batch, update, query)
ParameterHandler:处理传入的SQL的参数,允许拦截的方法包括(getParameterObject, setParameters)
ResultSetHandler:处理SQL执行后返回的结果集,允许拦截的方法包括(handleResultSets, handleOutputParameters)
好,介绍完了mybatis的四个对象,那我们想实现自动化的填入创建人、创建时间等信息应该通过拦截哪个对象呢?思考一下,其实只需要在插入或修改数据时添加字段即可,实际上就是在SQL执行insert、update语句去设置。所以我们对SQL执行器Executor进行拦截操作即可。好,那么接下来具体实现下。
开始自己的第一个MyBatis插件
首先需要实现Interceptor接口,Interceptor接口中有三个方法,分别是:intercept(Invocation invocation);plugin(Object o);setProperties(Properties properties)。intercept方法是最终拦截的方法,我们的逻辑代码就是加在里面;plugin方法返回一个代理对象,我们直接调用MyBatis提供的Plugin.wrap即可;setProperties就是配置一些自定义属性。
在创建的类上需要加@Intercepts,标记为拦截器类;@Signature是@Intercepts的一个属性,表示拦截哪些方法,可以拦截配置多个,拦截多个方法;@Signature中有多个属性,分别是type(拦截的组件名称),method(拦截的方法名),args(方法的参数)。
开始写我们的demo
@Intercepts(
@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class,Object.class}
)
)
public class ExecutorInterceptor implements Interceptor {
/**
* intercept
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
//接受SQL操作类型
SqlCommandType sqlCommandType = null;
Object[] args = invocation.getArgs();
for (Object arg : args) {
//获取操作类型
if (arg instanceof MappedStatement){
MappedStatement mappedStatement = (MappedStatement) arg;
sqlCommandType = mappedStatement.getSqlCommandType();
continue;
}
//根据参数类型赋值
if(arg instanceof CompanyVO){
Date now = DateUtil.now();
if(SqlCommandType.INSERT.equals(sqlCommandType)){
BeanUtils.setProperty(arg,"createTm",now);
BeanUtils.setProperty(arg,"updateTm",now);
BeanUtils.setProperty(arg,"creator","anyu~");
BeanUtils.setProperty(arg,"updater","anyu~");
}
if(SqlCommandType.UPDATE.equals(sqlCommandType)){
BeanUtils.setProperty(arg,"updateTm",now);
BeanUtils.setProperty(arg,"updater","anyu~~~");
}
}
}
return invocation.proceed();
}
/**
* plugin
* @param o
* @return
*/
@Override
public Object plugin(Object o) {
return Plugin.wrap(o,this);
}
/**
* setProperties
* @param properties
*/
@Override
public void setProperties(Properties properties) {
}
}
增加一个配置类,用来注入拦截器类;也可以使用配置文件,在这里不做赘述。
@Configuration
public class MyBatisConfiguration {
/**
* ExecutorInterceptor
* @return
*/
@Bean
public ExecutorInterceptor executorInterceptor(){
ExecutorInterceptor interceptor = new ExecutorInterceptor();
return interceptor;
}
}
我们是对新增和修改方法增加了拦截,所以增加一个updateById方法。下面的代码用到了标签,这是MyBatis的另一个强大的功能,动态SQL,我们在下一节去讲讲这个。
<!--根据id更新数据-->
<update id="updateById" parameterType="com.example.demo.company.vo.CompanyVO">
UPDATE t_company
<set>
<if test="name != null">
name = #{name},
</if>
<if test="region!=null">
region = #{region},
</if>
<if test="boss!=null">
boss = #{boss},
</if>
<if test="createTm!=null">
creator = #{creator},
</if>
<if test="createTm!=null">
create_tm = #{createTm},
</if>
<if test="updater!=null">
updater = #{updater},
</if>
<if test="updateTm!=null">
update_tm = #{updateTm},
</if>
</set>
where id = #{id}
</update>
开始测试,先测试新增方法,测试代码如下
@org.junit.Test
public void insertOne(){
CompanyVO companyVO = new CompanyVO();
companyVO.setBoss("小马哥");
companyVO.setName("腾讯");
companyVO.setRegion("深圳");
service.insertOne(companyVO);
}
然后测试修改方法,测试代码如下:
@org.junit.Test
public void updateById(){
CompanyVO companyVO = new CompanyVO();
companyVO.setId(1);
companyVO.setRegion("北京-亦庄");
service.updateById(companyVO);
}
从日志及MySQL可以看出,自定义插件对创建人、创建时间等字段进行了赋值,并成功插入或更新在数据库表中,符合预期。这样,我们的自定义插件就开发完了,可以减少一部分重复代码,以此为例子,可以思考一下当前的什么业务场景可以用呢?这些要靠自己发掘了。MyBatis也有很多非常好用的插件,比如分页插件PageHelper;通用Mapper插件,极其方便的实现单表增删改查;MyBatis-X可以快速生成实体类、mapper等等。
动态SQL
不知道大家有没有使用JDBC进行过开发,刚入行接手的第一个项目就是用的JDBC,因为业务要求,查询条件很多,要根据不同条件拼接不同的SQL,经常性的上百行,而且很容易哪边没拼好,就出错了,回想起那段时间那是相当的痛苦。MyBatis的动态SQL,彻底解决了这个麻烦。
动态SQL,即Dynamic SQL,通过各种标签对查询条件做出判断,实现动态拼接SQL语句,帮我们来实现部分逻辑;比如我们上一部分的标签,通过判断传入的值是否为null,决定是否拼接相应的SQL语句。
接下来我们介绍下常用的标签及用法。
If标签
if标签类似于Java中的if判断语句,该标签通常与where或者update连用,比如我们之前写的updateById语句,或者比如下面的查询语句:
<!--根据条件查询-->
<select id="selectByCondition" parameterType="com.example.demo.company.vo.CompanyVO" resultMap="BaseResultMap">
select * from t_company
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="region!=null">
AND region = #{region}
</if>
<if test="boss!=null">
AND boss = #{boss}
</if>
</where>
</select>
foreach标签
foreach标签是对集合进行遍历,和Java语言中的遍历相似,经常与in语句连用。常用场景通常和批量相关,比如批量插入、批量删除,或者拼接查询语句的条件也常常用到。下面分别是一个查询和批量插入的例子
<!--根据id集合查询-->
<select id="selectByIds" parameterType="java.util.List" resultMap="BaseResultMap">
select * from t_company where id in
<foreach collection="list" index="index" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</select>
<!--插入全部,之前的拦截器并不兼容批量操作,这部分就作业自行实现吧-->
<insert id="insertAll" parameterType="java.util.List">
INSERT INTO t_company
(name, region, boss, creator,
create_tm, updater, update_tm
)
VALUES
<foreach collection="list" item="item" separator="," index="index">
(#{item.name}, #{item.region}, #{item.boss},
#{item.creator}, #{item.createTm}, #{item.updater}, #{item.updateTm})
</foreach>
</insert>
choose, when, otherwise标签
这些标签类似于Java语句中Switch,case,default;根据条件去选择需要拼接的SQL语句。比如,下面的语句,根据传入参数的判断,name不为空时,拼接name条件,若为空时则继续向下判断,一次类推。
<!--根据条件优先级查询-->
<select id="selectByPri" parameterType="com.example.demo.company.vo.CompanyVO" resultMap="BaseResultMap">
select * from t_company where 1=1
<choose>
<when test="name != null">
AND name = #{name}
</when>
<when test="region != null">
AND region = #{region}
</when>
<when test="boss != null">
AND boss = #{boss}
</when>
<otherwise>
AND id = #{id}
</otherwise>
</choose>
</select>
sql,include标签
SQL和include标签,通常搭配使用;对于一些重复的SQL语句,比如查询的字段,查询条件等等,这两个搭配使用,可以有效减少代码量。下面的是修改之前的查询语句,以此为例
<!--查询字段语句块-->
<sql id="field">
id,name,region,boss,creator,create_tm,updater,update_tm
</sql>
<!--根据ID查询-->
<select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
SELECT
<include refid="field"/>
FROM t_company
WHERE id=#{id}
</select>
where,set标签
where标签会自动生成where关键字,并且会将多余的and或or去掉,避免多余的and或or引起的SQL语句错误;和where标签类似,set标签会自动生成set关键字,并去掉多余的逗号,避免因为多余的逗号引起的错误。where标签和set标签,在上文中均有例子,就不在重复写了。
trim标签
trim标签是一个格式化的标签,是针对trim标签内的语句的首尾进行删除或添加的,表述的有点绕口,所以我们还是上案例吧。
<!--根据条件查询-->
<select id="selectByCondition" parameterType="com.example.demo.company.vo.CompanyVO" resultMap="BaseResultMap">
select * from t_company
<trim prefix="where" prefixOverrides="AND">
<if test="name != null">
AND name = #{name}
</if>
<if test="region!=null">
AND region = #{region}
</if>
<if test="boss!=null">
AND boss = #{boss}
</if>
</trim>
</select>
从上面xml中的语句和打印的最终执行的SQL语句可以看出来,trim标签把第一个if标签中的and替换成了where,类似于Java中的replace方法,这相当于用trim标签做了一个where标签的功能。trim相当于一个字符串处理工具,当然它不仅可以处理句首,还可以处理句尾,我们看下面的例子。
<!--根据id更新数据-->
<update id="updateById" parameterType="com.example.demo.company.vo.CompanyVO">
UPDATE t_company
<trim prefix="set" prefixOverrides="" suffix="" suffixOverrides=",">
<if test="name != null">
name = #{name},
</if>
<if test="region!=null">
region = #{region},
</if>
<if test="boss!=null">
boss = #{boss},
</if>
<if test="createTm!=null">
creator = #{creator},
</if>
<if test="createTm!=null">
create_tm = #{createTm},
</if>
<if test="updater!=null">
updater = #{updater},
</if>
<if test="updateTm!=null">
update_tm = #{updateTm},
</if>
</trim>
where id = #{id}
</update>
上面的例子,实现了一个set标签的功能,即在句首加了一个set关键字,并把句尾的逗号去掉了。trim标签实际用到的业务场景还是很少的,因为其他的标签就足够强大足够用了;但是,当我们绞尽脑汁想完成一个功能,其他标签也不满足的时候,也不要忘了它,没准会有意想不到的惊喜。
复杂映射开发
回顾我们之前的内容,可以发现,上面的所有例子全部是针对单表的操作,如果是面对表关联查询的场景呢?MyBatis提供了面对一对一、一对多等复杂业务场景的处理方式,下面我们就分开来唠唠。
一对一
我们需要再建一个表,就建一个boss表吧,建表语句如下
CREATE TABLE `t_boss` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(50) DEFAULT NULL COMMENT '姓名',
`sex` varchar(50) DEFAULT NULL COMMENT '性别',
`creator` varchar(50) DEFAULT NULL COMMENT '创建者',
`create_tm` timestamp DEFAULT NULL COMMENT '创建时间',
`updater` varchar(50) DEFAULT NULL COMMENT '修改者',
`update_tm` timestamp DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='老板'
直接插入几条数据
INSERT INTO t_boss
( name, sex, creator, create_tm, updater, update_tm)
VALUES( '东哥', '男', 'anyu~', '2023-03-30 17:12:36', 'anyu~~~', '2023-03-21 17:06:36');
INSERT INTO t_boss
( name, sex, creator, create_tm, updater, update_tm)
VALUES( '小马哥', '男', 'anyu~', '2023-03-30 17:12:36', 'anyu~~~', '2023-03-21 17:06:36');
INSERT INTO t_boss
( name, sex, creator, create_tm, updater, update_tm)
VALUES( '雷布斯', '男', 'anyu~', '2023-03-30 17:12:36', 'anyu~~~', '2023-03-21 17:06:36');
INSERT INTO t_boss
( name, sex, creator, create_tm, updater, update_tm)
VALUES( '风清扬', '男', 'anyu~', '2023-03-30 17:12:36', 'anyu~~~', '2023-03-21 17:06:36');
新增实体类
@Data
public class BossVO {
/**
* id
*/
private Integer id;
/**
* 名称
*/
private String name;
/**
* 区域
*/
private String sex;
/**
* 公司
*/
private CompanyVO companyVO;
}
查询方法和resultMap
<resultMap id="BaseResultMap" type="com.example.demo.company.vo.BossVO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="sex" jdbcType="VARCHAR" property="sex" />
<association property="companyVO" javaType="com.example.demo.company.vo.CompanyVO">
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="region" jdbcType="VARCHAR" property="region" />
<result column="boss" jdbcType="VARCHAR" property="boss" />
</association>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select tb.id,tb.name,tb.sex,tc.name ,tc.region ,tc.boss
from t_boss tb left join t_company tc on tb.name = tc.boss
</select>
测试下代码,具体调就自己实现吧,测试日志如下
我们在一对一关联中,用到了association 标签,主要用于一对一的业务场景。当一对多的场景时,会用到另一个标签,collection,示例如下
一对多
针对一对多的业务场景,我们在t_company表在插入几条数据,插入语句如下
INSERT INTO t_company
( name, region, boss)
VALUES( '阿里云', '杭州', '风清扬');
INSERT INTO t_company
( name, region, boss)
VALUES('腾讯游戏', '深圳', '小马哥');
INSERT INTO t_company
(name, region, boss)
VALUES( '腾讯体育', '深圳', '小马哥');
INSERT INTO t_company
( name, region, boss)
VALUES('京东物流', '北京-亦庄', '东哥');
INSERT INTO t_company
(name, region, boss)
VALUES( '京东科技', '北京-亦庄', '东哥');
修改下BossVO实体类
@Data
public class BossVO {
/**
* id
*/
private Integer id;
/**
* 名称
*/
private String name;
/**
* 区域
*/
private String sex;
/**
* 公司
*/
private List<CompanyVO> companyVOS;
}
修改resultMap如下
<resultMap id="BaseResultMap" type="com.example.demo.company.vo.BossVO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="sex" jdbcType="VARCHAR" property="sex" />
<collection property="companyVOS" ofType="com.example.demo.company.vo.CompanyVO">
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="region" jdbcType="VARCHAR" property="region" />
<result column="boss" jdbcType="VARCHAR" property="boss" />
</collection>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select tb.id,tb.name,tb.sex,tc.name ,tc.region ,tc.boss
from t_boss tb left join t_company tc on tb.name = tc.boss
</select>
查询结果日志如下
MyBatis的懒加载
懒加载也就是延时加载或者按需加载,当有使用时才会去加载。在关联查询的业务场景中,先查询主表,当有使用要求时,才会去关联查询子表,这样可以减轻对数据库的压力。我们改造一对多的例子,看下延时加载的
首先我们增加下延时加载的配置。
#懒加载
mybatis.configuration.lazy-loading-enabled=true
改造下之前一对多的查询代码
<resultMap id="BaseResultMap" type="com.example.demo.company.vo.BossVO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="sex" jdbcType="VARCHAR" property="sex" />
<collection property="companyVOS" ofType="com.example.demo.company.vo.CompanyVO"
select="selectCompanyByBoss" column="name" >
</collection>
</resultMap>
<select id="findAll" resultMap="BaseResultMap">
select tb.id,tb.name,tb.sex
from t_boss tb
</select>
<select id="selectCompanyByBoss" resultType="com.example.demo.company.vo.CompanyVO">
select name,region,boss from t_company WHERE boss=#{name}
</select>
下面是测试代码及日志,还有日志说明
@org.junit.Test
public void findAll(){
System.out.println("第一次查询开始~~~~~");
List<BossVO> all = bossService.findAll();
System.out.println("第一次查询结束~~~~~");
for (BossVO bossVO : all) {
System.out.println(bossVO.getName()+" 遍历,打印开始~~~~~");
System.out.println(bossVO.getCompanyVOS().toString());
System.out.println(bossVO.getName()+" 遍历,打印结束~~~~~");
}
}
配置文件中的 mybatis.configuration.lazy-loading-enabled=true 是全局性的,对于个别查询语句有特殊要求时,可在局部配置,局部配置项的优先级是高于全局配置的,我们再在之前的查询语句作出修改,我们增加一个取消懒加载的配置,当然fetchType也可以单独配置懒加载
查看查询日志,显然进行了实时加载。
结语
就写到这里吧,十分感谢你能看懂这里,希望通过这篇文章,让大家对MyBatis有个初步的了解,还有一些没有提到的地方,比如注解开发、比如MyBatis的缓存,因为感觉平时用不到或很少用,就没写,如果大家感兴趣,可以找一下其他博文。示例有很多不规范的地方,请大家宽容。