万字长文!一篇搞定MyBatis!

一句话介绍MyBatis

MyBatis是一款优秀的基于ORM的半自动轻量级持久层框架。抓取关键字:基于ORM、半自动、轻量级、持久化,接下来一一解释。

基于ORM

何为ORM? ORM即Object Relational Mapping,对象关系映射,ORM完成了对象到数据库的映射。可以理解为程序对象和数据库中表之间的桥梁,ORM框架将面向对象的操作转化为了对数据库中表的操作,大大提高了开发效率。

半自动

有半自动化,就有自动化。全自动化框架比较典型的就是Hibernate,它无需手写SQL,直接操作对象即可,好处是大大降低了对象与数据库的耦合性,可移植性好,但是面对复杂业务,实现及优化困难;Mybatis需要手写SQL,更加灵活,可以使后端代码与SQL功能分离,边界清晰,但是可移植性差,做过数据库迁移的都懂哈。

轻量级

重量级的框架,在启动的时候需要消耗大量的资源,内存,CPU等,比如EJB,本身也有120M;而轻量级框架,比如我们讲的Mybatis,在启动时消耗的资源就少很多,自身也只有不到3M。

持久化

持久化,顾名思义,就是对持久层进行操作,将对象永久的保存在数据库中。

快速入门

上文了解了MyBatis的基本信息,现在开始准备第一个简单的demo。

准备张表

 

sql

代码解读

复制代码

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项目,并引入以下依赖

 

xml

代码解读

复制代码

<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>

添加连接数据库相关配置信息,填写自己所连数据库信息

整理了这份Java面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

需要全套面试笔记【点击此处】即可免费获取

ini

代码解读

复制代码

#数据库连接配置信息 spring.datasource.url=jdbc:mysql://**** spring.datasource.username=**** spring.datasource.password=**** spring.datasource.driver-class-name=com.mysql.jdbc.Driver

创建公司表的实体类

 

arduino

代码解读

复制代码

@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类

 

java

代码解读

复制代码

@Mapper public interface CompanyMapper { /** * 根据ID查询 * @param id * @return */ CompanyVO selectById(Integer id); /** * 插入一条数据 * @param companyVO */ void insertOne(CompanyVO companyVO); }

创建mapper.xml,mapper建在resource目录下,路径需要和mapper类一致。注意:要一层一层建

 

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.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类

 

typescript

代码解读

复制代码

@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); } }

创建测试类,进行测试

 

less

代码解读

复制代码

@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语句,可以在配置文件中,加入下面配置

 

ini

代码解读

复制代码

#日志打印 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

 

typescript

代码解读

复制代码

@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) { } }

增加一个配置类,用来注入拦截器类;也可以使用配置文件,在这里不做赘述。

 

java

代码解读

复制代码

@Configuration public class MyBatisConfiguration { /** * ExecutorInterceptor * @return */ @Bean public ExecutorInterceptor executorInterceptor(){ ExecutorInterceptor interceptor = new ExecutorInterceptor(); return interceptor; } }

我们是对新增和修改方法增加了拦截,所以增加一个updateById方法。下面的代码用到了标签,这是MyBatis的另一个强大的功能,动态SQL,我们在下一节去讲讲这个。

 

bash

代码解读

复制代码

<!--根据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>

开始测试,先测试新增方法,测试代码如下

 

java

代码解读

复制代码

@org.junit.Test public void insertOne(){ CompanyVO companyVO = new CompanyVO(); companyVO.setBoss("小马哥"); companyVO.setName("腾讯"); companyVO.setRegion("深圳"); service.insertOne(companyVO); }

image.png

image.png

然后测试修改方法,测试代码如下:

 

java

代码解读

复制代码

@org.junit.Test public void updateById(){ CompanyVO companyVO = new CompanyVO(); companyVO.setId(1); companyVO.setRegion("北京-亦庄"); service.updateById(companyVO); }

image.png

image.png

从日志及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语句,或者比如下面的查询语句:

 

xml

代码解读

复制代码

<!--根据条件查询--> <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语句连用。常用场景通常和批量相关,比如批量插入、批量删除,或者拼接查询语句的条件也常常用到。下面分别是一个查询和批量插入的例子

 

xml

代码解读

复制代码

<!--根据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条件,若为空时则继续向下判断,一次类推。

 

xml

代码解读

复制代码

<!--根据条件优先级查询--> <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语句,比如查询的字段,查询条件等等,这两个搭配使用,可以有效减少代码量。下面的是修改之前的查询语句,以此为例

 

xml

代码解读

复制代码

<!--查询字段语句块--> <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标签内的语句的首尾进行删除或添加的,表述的有点绕口,所以我们还是上案例吧。

 

xml

代码解读

复制代码

<!--根据条件查询--> <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>

image.png

从上面xml中的语句和打印的最终执行的SQL语句可以看出来,trim标签把第一个if标签中的and替换成了where,类似于Java中的replace方法,这相当于用trim标签做了一个where标签的功能。trim相当于一个字符串处理工具,当然它不仅可以处理句首,还可以处理句尾,我们看下面的例子。

 

bash

代码解读

复制代码

<!--根据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>

image.png

上面的例子,实现了一个set标签的功能,即在句首加了一个set关键字,并把句尾的逗号去掉了。trim标签实际用到的业务场景还是很少的,因为其他的标签就足够强大足够用了;但是,当我们绞尽脑汁想完成一个功能,其他标签也不满足的时候,也不要忘了它,没准会有意想不到的惊喜。

复杂映射开发

回顾我们之前的内容,可以发现,上面的所有例子全部是针对单表的操作,如果是面对表关联查询的场景呢?MyBatis提供了面对一对一、一对多等复杂业务场景的处理方式,下面我们就分开来唠唠。

一对一

我们需要再建一个表,就建一个boss表吧,建表语句如下

 

sql

代码解读

复制代码

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='老板'

直接插入几条数据

 

sql

代码解读

复制代码

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');

新增实体类

 

arduino

代码解读

复制代码

@Data public class BossVO { /** * id */ private Integer id; /** * 名称 */ private String name; /** * 区域 */ private String sex; /** * 公司 */ private CompanyVO companyVO; }

查询方法和resultMap

 

ini

代码解读

复制代码

<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>

测试下代码,具体调就自己实现吧,测试日志如下

image.png

我们在一对一关联中,用到了association 标签,主要用于一对一的业务场景。当一对多的场景时,会用到另一个标签,collection,示例如下

一对多

针对一对多的业务场景,我们在t_company表在插入几条数据,插入语句如下

 

sql

代码解读

复制代码

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实体类

 

arduino

代码解读

复制代码

@Data public class BossVO { /** * id */ private Integer id; /** * 名称 */ private String name; /** * 区域 */ private String sex; /** * 公司 */ private List<CompanyVO> companyVOS; }

修改resultMap如下

 

ini

代码解读

复制代码

<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>

查询结果日志如下

image.png

MyBatis的懒加载

懒加载也就是延时加载或者按需加载,当有使用时才会去加载。在关联查询的业务场景中,先查询主表,当有使用要求时,才会去关联查询子表,这样可以减轻对数据库的压力。我们改造一对多的例子,看下延时加载的

首先我们增加下延时加载的配置。

 

ini

代码解读

复制代码

#懒加载 mybatis.configuration.lazy-loading-enabled=true

改造下之前一对多的查询代码

 

ini

代码解读

复制代码

<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>

下面是测试代码及日志,还有日志说明

 

csharp

代码解读

复制代码

@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()+" 遍历,打印结束~~~~~"); } }

image.png

配置文件中的 mybatis.configuration.lazy-loading-enabled=true 是全局性的,对于个别查询语句有特殊要求时,可在局部配置,局部配置项的优先级是高于全局配置的,我们再在之前的查询语句作出修改,我们增加一个取消懒加载的配置,当然fetchType也可以单独配置懒加载

image.png

查看查询日志,显然进行了实时加载。

image.png

结语

就写到这里吧,十分感谢你能看懂这里,希望通过这篇文章,让大家对MyBatis有个初步的了解,还有一些没有提到的地方,比如注解开发、比如MyBatis的缓存,因为感觉平时用不到或很少用,就没写,如果大家感兴趣,可以找一下其他博文。示例有很多不规范的地方,请大家宽容。

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值