mybatis学习知识点摘录

前言:

Mybatis的使用是基于XML配置,不同于hibernate直接写在java代码中,所以其解耦性很好,而且轻量级,可以灵活处理各种SQL语句,要说缺点,暂时我能想的就是要写很多东西,而且XML是很难发现有报错的,但是一般而言一个模块写好的公共的resultMap以及sql后,后面的就方便了很多。这篇文章不是基础,而是针对基础的一些需要注意的知识点的总结摘录,尤其要注意的是Mybatis针对不同数据库,比如mysql和oracle在很多配置以及具体SQL写法上是有很多不同的,举个栗子批量插入数据时几乎完全不同!但是我们搜索的mybatis教程可以说100个里面99个都是拿mysql做例子,而实际中oracle用的也比较多。所以针对以上我做了具体摘录。
第一大部分是基础知识总结,第二部分进阶请等待我的更新。欢迎留言指出不足和纰漏!

一、Mybatis基础知识点:

1.动态代理技术使得mapper.xml类似于daoImpl,mapper.java只是interface,无实现类
2.mybatis-config里面的标签,比如<properties>,<environment>等,注意,是有先后顺序的,不可颠倒。
3.自增主键(mysql支持自增)
非自增(oracle)


3.mybatis mapper接口怎么 传递多个参数 @Param()注解
3.1当传递一个参数的时候,不做特殊处理 直接#{}
3.2当传递多个参数的时候,mybatis会封装

这个mapper.java接口里面的两个参数是没加注解的
所以使用的时候就得传入mybatis封装的这种param1 param2的方式



当使用注解了后 就明确了参数

使用注解后mybatis会将多个参数自动封装成map

这样mapper.xml可以如下




以上这种@Params注解适用于 参数不多的情况(几个)
多个参数的话(比如一个对象)
需要如下三种方式(第二种直接封装成map比较常见,第三种是自定义扩展类,第一种就是原始的POJO)

Map封装参数如下:

mapper.xml里面直接拿map的key取值




几种特殊的传递参数




4.$ #区别:
#{}预编译,可以防止SQL注入。
#{}用来传查询参数
${}直接拼接在SQL语句里面
排序order by ${} 表明:select * from ${tableName} where id=#{id} order by ${name}

5. #{}扩展,对oracle数据库无法识别mybtais对null的处理,所以当数据为null时候插入数据会报错,解决办法: #{parameter,jdbcType=OTHER}
mysql是没这个问题的,可以识别NULL
但是实际应用中我们都是判断如果为NULL就不插入,以上是原生的情况

在向oracle插入数据时,mybatis3报Error setting null parameter. Most JDBC drivers require that the JdbcType must be specified for all nullable parameters,是由于参数出现了null值,对于Mybatis,如果进行操作的时候,没有指定jdbcType类型的参数,mybatis默认jdbcType.OTHER导致,给参数加上jdbcType可解决(注意大小写) 


6.当Mapper.java接口里面方法返回值为List<Object>的时候,这时对应Mapper.xml文件的select语句的resultType(不是resultMap)还是写Object对象名称 mybatis会自动处理封装返回结果集的。

7.返回值类型为Map
单条对象:
方法:public Map< String,Object> getEmpById(Integer id)
mapper.xml: resultMap="map"(不用写全称)
多条对象:
方法:加注解 MapKey("id") 每条对象数据的id作为Map的key public Map< Integer,Object> getEmpById(Integer id)
因为id是Integer类型所以key是Integer,如果用name做key,那么就用String
mapper.xml:resultMap="com.wonder.Emp" (对象路径)

8.关联查询配合延迟加载,会提升效率;比如查询Emp里面1对1关联Dept,这个Dept的查询是单独的然后和Emp的查询组合关联到一起,这样当配置延迟加载后,我们查Emp的时候如果不用Dept里面的属性,那么就执行查询Emp的一条SQL,如果用到了Dept里面的属性,就执行Emp Dept两条SQL。
如果没有配置延迟加载,那么查Emp不管是否用到Dept的属性都会执行两条SQL。

9.分步查询传多个参数:(dept是主表, emp是从表(List<Emp>))
fetchType设置成eager就没延迟加载效果了(就会两个SQL一起发,而延迟加载是用到了才发从表Emp的SQL)

10.<discriminator>根据字段的取值进行处理结果,比如在此gender=0是女生 返回特定结果 gender=1是男生 根据情况再返回特定结果


resutType或者ResultMap不可缺少,这里用的是resultType,我们可以自定义用resultMap返回制定规则下数据


11. if 标签 OGNL表达式
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id=#{id} and
</if>
<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
last_name like #{lastName} and
</if>
<if test="email!=null and email.trim()!=&quot;&quot;">
email=#{email} and
</if>
<!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
<if test="gender==0 or gender==1">
gender=#{gender}
</if>
</trim>

12、查询条件多出的and 或者or 解决办法
1)where 1=1 或者
2) 推荐:<where>标签 将所有的查询条件包括在内 这个where会处理
<if test="email!=null and email.trim()!=&quot;&quot;">
andemail=#{email}
</if>
这种and在参数前的情况,但是没法解决 and在后这种 拼接还是会多出and
3)如果是:
<if test="email!=null and email.trim()!=&quot;&quot;">
email=#{email} and
</if>
得用 <trim>标签解决(自定义截取,也不是首选)
后面多出的and或者or where标签不能解决
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符

13. <choose>标签
<select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee
<where>
<!-- 如果带了id就用id查,如果带了lastName就用lastName查; 只会进入其中一个 -->
<choose>
<when test="id!=null">
id=#{id}
</when>
<when test="lastName!=null">
last_name like #{lastName}
</when>
<when test="email!=null">
email = #{email}
</when>
<otherwise>
gender = 0
</otherwise>
</choose>
</where>
</select>

如果id和lastName都有值得话 那么也只是进入一个分支,id在前,就只进入id分支

14. <set>标签:可以去除 多余的 , 逗号
<update id="updateEmp">
<!-- Set标签的使用 -->
update tbl_employee
<set>
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</set>
where id=#{id}
或者:
Trim:更新拼串
update tbl_employee
<trim prefix="set" suffixOverrides=" , ">
<if test="lastName!=null">
last_name=#{lastName},
</if>
<if test="email!=null">
email=#{email},
</if>
<if test="gender!=null">
gender=#{gender}
</if>
</trim>
where id=#{id}
</update>

15. <foreach>标签,Mapper.java传的是一个ids的List
<select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee
<!--
collection:指定要遍历的集合:
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list的时候是index就是索引,item就是当前值
遍历map的时候index表示的就是map的key,item就是map的值
#{变量名}就能取出变量的值也就是当前遍历出的元素
-->
<foreach collection="ids" item="item_id" separator=","
open="where id in(" close=")">
#{item_id}
</foreach>
</select>

16. MySQL下批量 保存------ <foreach>标签批量保存数据,Mapper.java:public void addEmps(@Param("emps") List<Employee> emps);
<!--public void addEmps(@Param("emps")List<Employee> emps); -->
<!-- MySQL下批量保存:可以foreach遍历 mysql支持values(),(),()语法-->
第一种(常用),一条SQL,循环插入的数据对象:
<insert id="addEmps">
insert into tbl_employee(
<include refid="insertColumn"></include>
)
values
<foreach collection="emps" item="emp" separator= ",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{ emp.dept.id})
</foreach>
</insert>
第二种( 这种形式也可以可以批量删除,修改 ),发送多条SQL,循环执行多条SQL语句:
<!-- 这种方式需要数据库连接属性 allowMultiQueries=true
这种分号分隔多个sql可以用于其他的批量操作( 删除,修改) -->
<!-- <insert id="addEmps">
<foreach collection="emps" item="emp" separator= ";">
insert into tbl_employee(last_name,email,gender,d_id)
values(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert> -->

17 .Oracle数据库批量操作
注意:和mysql不同
CSDN:下面来看一个Oracle例子:
 首先,在DataMapper. Java  接口类中加入接口:
[java]   view plain   copy
  1. int batchInsert(List<Data> datas);  
  然后,在xxxMapper.xml 中编写对应的实现sql,我使用的是oracle,如果是mysql或sqlserver,可能sql语句会略有区别吧:
[xml]   view plain   copy
  1. <insert id="batchInsert"parameterType="java.util.List">   
  2.  insert into DATA (ID, TEXT, STAUTS)   
  3.  <foreach close=")"collection="list"item="item"index="index"open="("separator="union">   
  4. select  
  5. #{item.id,jdbcType=VARCHAR},  
  6. #{item.text,jdbcType=VARCHAR},  
  7. #{item.stauts,jdbcType=VARCHAR}  
  8.  from dual   
  9. </foreach>  
  10. </insert>  

Oracle第一种批量插入方式(执行多个单条插入的SQL------多个insert放在begin - end里面):
<insert id="addEmps" databaseId="oracle">
<foreach collection="emps" item="emp" open="begin" close= "end;">
insert into employees(employee_id,last_name,email)
values(employees_seq.nextval,#{emp.lastName},#{emp.email});
</foreach>
</insert>

Oracle第二种批量插入方式(利用中间表):
<insert id="addEmps" databaseId="oracle">
insert into employees(
<!-- 引用外部定义的sql -->
<include refid="insertColumn">
<property name="testColomn" value="abc"/>
</include>
)
<foreach collection="emps" item="emp" separator="union"
open="select employees_seq.nextval,lastName,email from("
close=")">
select #{emp.lastName} lastName,#{emp.email} email from dual
</foreach>
</insert>

批量更新:

<update id="updateBatch" parameterType="java.util.List">
    begin  
        <foreach collection="list" item="item" index="index" separator=";" > 
            update Emp
            <set>
            <if test="item.id!=null and item.id!=''">
                id = #{item.id},
            </if>

            <if test="item.name!=null and item.name!=''">
                NAME= #{item.name},
            </if>

            </set>
            where id = #{item.id}
            </foreach>
        ;end;
    </update>

批量删除:

<delete id="deleteBatch" parameterType="java.util.List">
  delete from Emp
  <where>
  <foreach collection="list" index="index" item="item" open="(" separator="or" close=")">     
  id=#{item.id}
    </foreach>
  </where>
  </delete>


18.mybatis的两个内置参数:不只是方法传递过来的参数可以被用来判断,取值。
mybatis默认还有两个内置参数:
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装为一个map;_parameter就是代表这个map
_databaseId:如果配置了databaseIdProvider标签。
_databaseId就是代表当前数据库的别名oracle

_databaseId是在mybatis-config.xml中配置的:
<!-- databaseIdProvider:支持多数据库厂商的;
type="DB_VENDOR":VendorDatabaseIdProvider
作用就是得到数据库厂商的标识(驱动getDatabaseProductName()),mybatis就能根据数据库厂商标识来执行不同的sql;
MySQL,Oracle,SQL Server,xxxx
-->
<databaseIdProvider type="DB_VENDOR">
<!-- 为不同的数据库厂商起别名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>


接口:public List<Employee> getEmpsTestInnerParameter(Employee employee);
<select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
<!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 ----不推荐,建议直接在mapper.java接口里面把%param%这样传过来->
<bind name="_lastName" value="'%'+lastName+'%'"/>
<if test="_databaseId==' mysql'">
select * from tbl_employee
<if test="_parameter!=null">
where last_name like #{lastName}
</if>
</if>
<if test="_databaseId==' oracle'">
select * from employees
<if test="_parameter!=null">
where last_name like #{_parameter .lastName}
</if>
</if>
</select>
<!--
抽取可重用的sql片段。方便后面引用
1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
2、include来引用已经抽取的sql:
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
include-property:取值的正确方式${prop},
#{不能使用这种方式}
-->
<sql id="insertColumn">
<if test="_databaseId=='oracle'">
employee_id,last_name,email
</if>
<if test="_databaseId=='mysql'">
last_name,email,gender,d_id
</if>
</sql>

19.mybatis做模糊查询常用方法:
使用 ${...} 代替 #{...}  SELECT * FROM tableName WHERE name LIKE '%${text}%';

20.SQL标签抽取重用的SQL片段:
<!--
抽取可重用的sql片段。方便后面引用
1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
2、include来引用已经抽取的sql:
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
include-property:取值的正确方式${prop},
#{不能使用这种方式}
-->
<sql id="insertColumn">
<if test="_databaseId=='oracle'">
employee_id,last_name,email
</if>
<if test="_databaseId=='mysql'">
last_name,email,gender,d_id
</if>
</sql>

二、Mybatis进阶:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值