一般动态标签主要有if标签,用来写一写条件语句
<if test="userId!=null">
and a.user_id= #{userId}
if>
条件较多的时候使用choose标签
<choose>
<when test="dbType=='mysql'">
order by er.money
limit 1
when>
<when test="dbType=='oracle'">
and rownum = 1
order by er.money
when>
choose>
格式化标签trim
select * from user
<trim prefix="WHERE" prefixoverride="AND |OR">
<if test="name != null and name.length()>0"> AND name=#{name}if>
<if test="gender != null and gender.length()>0"> AND gender=#{gender}if>
trim>
prefix:前缀
prefixoverride:去掉第一个and或者是or
foreach标签,和chosse搭配使用
<choose>
<when test="list != null and list.size() > 0">
h.id in
<foreach collection="list" item="id" index="index" open="(" close=")" separator=",">
#{id}
foreach>
when>
<otherwise>
h.id< -99999
otherwise>
choose>
这个场景是出现最多的,比如接口啥的。
核心的思路就是,减少数据库交互,控制好一次性插入的记录行数
一般来讲有三种解决方案
这里就不介绍了,不同公司可能有不同的方法
设置mybatis的sqlsession的ExecutorType为batch,如果用Jdbc则用executeBatch
这里注意的两点是
1.将MyBatis session的executor type 设为Batch,而mybatis的默认执行器类型是Simple,这样的设置大大节约了每次创建新的预处理语句的时间
2.session工厂在获取session实例的时候,传了一个false过去,默认值是true是会自动提交的,这里改为手动提交,避免频繁与数据库交互。
3.此方法的使用,在网上有很多推荐,感兴趣的可以搜一下,有很详细的使用样例。
但是经过我的测试,传入一个size为10000的list,session.commit的执行时间竟然达到了14分钟,很夸张。网上也没找到合适的说法,我只能理解为这只是节约了java层创建PreparedStatement对象的时间,但是commit提交到数据库的时候,执行方式还是将10000条insert去逐步执行。所以导致很慢。
最简单也是实测最有效的方法
原理就是insert into table(a,b,c) value(1,2,3),insert into table(a,b,c) value(4,5,6)
与insert into table(a,b,c) value(1,2,3)(4,5,6)的区别
如果插入的行足够的多,那么两种方式的效率是有很大差别的
当然,这并不意味着要一次性传入过多的行,太长的话不光会导致效率下降,甚至会报错。
所以这个方法的关键就是如何合理的切割你要传入的list
一个list切割方法:
使用很简单,就是看length的大小怎么合理分配,这是网上的一个参考图
行数和效率不是一个正比的曲线
但是他的数据量很显然和我们使用的又不太一致,所以我个人测试了几种方式如下
总数据量:70115
表行数:12
X轴:70115条数据单次分割大小,单位1000
Y轴:70115条数据插入总共需要的时间,单位秒
由此我们也可以简单的看出来,确实是有一个最低点的,大约就在1W条左右
使用场景较少,一般都是逻辑都是放在java中的,不然不利于维护
使用场景也较少,删除一般都是通过主键删除
一般而言,我们很少做单表查询,如果是多表关联查询,比如查询文章的同时查询作者信息,就需要结果里有两张表的字段。这时候有四种处理方案来接受并封装结果。
<resultMap id="BlogWithAuthorResultMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<association property="author" javaType="com.gupaoedu.domain.Author">
<id column="author_id" property="authorId"/>
<result column="author_name" property="authorName"/>
association>
resultMap>
第二种,查询嵌套型
<resultMap id="BlogWithAuthorQueryMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
<id column="bid" property="bid" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<association property="author" javaType="com.gupaoedu.domain.Author" column="author_id" select="selectAuthor"/>
resultMap>
<select id="selectAuthor" parameterType="int" resultType="com.gupaoedu.domain.Author">
select author_id authorId, author_name authorName from author where author_id = #{authorId}
select>
第一种好理解,就是一个结果集的封装
第二种其实是分两次查询,第一次查询文章,假设查询一次之后返回结果集10条(一次),然后根据这10条数据再去找对应的作者,再发送10次请求到数据库(N次),这样是损耗数据库性能的
所以就可以使用我们的延迟加载
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="proxyFactory" value="CGLIB" />
懒加载其实就是这样的
第一次查询,只会查询文章
之后,只有调用到blog.getAuthor()这个方法的时候,才会触发第二次查询,否则的话就偷懒不查询了
原理也很简单,当我们输出blog.getClass()的时候,发现它是一个类似BlogAndAuthor_$$_jvst70_0这种的代理对象,否则的话无法做到调用它的一个方法,就能触发查询的效果的,肯定是做了逻辑处理。
上面setting的配置中可以指定代理的工具
分为逻辑分页和物理分页
逻辑分页其实就是假分页,对性能上没啥改善,只是效果上的改变
物理分页是数据库层面的分页,对性能是有改善的,体现在sql中,就是MySQL会生成 limit 语句,Oracle会生成 rownum 语句,SQL Server会生成 top 语句。常用的工具PageHelper
它是一款mybatis的增强工具包,增加了通用的crud,条件构造器(java中拼接sql条件)、代码生成器(或者公司自己开发的)等