前言:
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里面的标签,比如
,等,注意,是有先后顺序的,不可颠倒。
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的时候,这时对应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))
fetchType设置成eager就没延迟加载效果了(就会两个SQL一起发,而延迟加载是用到了才发从表Emp的SQL)
10.根据字段的取值进行处理结果,比如在此gender=0是女生 返回特定结果 gender=1是男生 根据情况再返回特定结果
resutType或者ResultMap不可缺少,这里用的是resultType,我们可以自定义用resultMap返回制定规则下数据
11.
if 标签 OGNL表达式
id=#{id} and
last_name like #{lastName} and
email=#{email} and
gender=#{gender}
12、查询条件多出的and 或者or 解决办法
1)where 1=1 或者
2)
推荐:标签 将所有的查询条件包括在内 这个where会处理
and email=#{email}
这种and在参数前的情况,但是没法解决 and在后这种 拼接还是会多出and
3)如果是:
email=#{email}
and
得用
标签 解决(自定义截取,也不是首选)
后面多出的and或者or where标签不能解决
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符
13.
标签
select * from tbl_employee
id=#{id}
last_name like #{lastName}
email = #{email}
gender = 0
如果id和lastName都有值得话 那么也只是进入一个分支,id在前,就只进入id分支
14.
标签 :可以去除
多余的 , 逗号
update tbl_employee
last_name=#{lastName},
email=#{email},
gender=#{gender}
where id=#{id}
或者:
Trim:更新拼串
update tbl_employee
suffixOverrides="
,
" >
last_name=#{lastName},
email=#{email},
gender=#{gender}
where id=#{id}
15.
标签,Mapper.java传的是一个ids的List
select * from tbl_employee
open="where id in(" close=")">
#{item_id}
16.
MySQL下批量
保存 ------
标签批量保存数据,Mapper.java:public void addEmps(@Param("emps") List emps);
第一种(常用),一条SQL,循环插入的数据对象:
insert into tbl_employee(
)
values
",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{
emp.dept.id} )
第二种(
这种形式也可以可以批量删除,修改
),发送多条SQL,循环执行多条SQL语句:
17
.Oracle数据库批量操作
注意:和mysql不同
CSDN:下面来看一个Oracle例子:
首先,在DataMapper.
Java
接口类中加入接口:
[java]
view plain
copy
int batchInsert(List datas);
然后,在xxxMapper.xml 中编写对应的实现sql,我使用的是oracle,如果是mysql或sqlserver,可能sql语句会略有区别吧:
[xml]
view plain
copy
id ="batchInsert" parameterType ="java.util.List" >
insert into DATA (ID, TEXT, STAUTS)
close =")" collection ="list" item ="item" index ="index" open ="(" separator ="union" >
select
#{item.id, jdbcType = VARCHAR },
#{item.text, jdbcType = VARCHAR },
#{item.stauts, jdbcType = VARCHAR }
from dual
Oracle第一种批量插入方式(执行多个单条插入的SQL------多个insert放在begin - end里面):
"end;">
insert into employees(employee_id,last_name,email)
values(employees_seq.nextval,#{emp.lastName},#{emp.email});
Oracle第二种批量插入方式(利用中间表):
insert into employees(
)
open="select employees_seq.nextval,lastName,email from("
close=")">
select #{emp.lastName} lastName,#{emp.email} email from dual
批量更新:
begin update Emp id = #{item.id},
NAME= #{item.name},
where id = #{item.id} ;end;
批量删除:
delete from Emp id=#{item.id}
18.mybatis的两个内置参数:不只是方法传递过来的参数可以被用来判断,取值。
mybatis默认还有两个内置参数:
_parameter :代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装为一个map;_parameter就是代表这个map
_databaseId :如果配置了databaseIdProvider标签。
_databaseId就是代表当前数据库的别名oracle
_databaseId是在mybatis-config.xml中配置的:
接口:public List getEmpsTestInnerParameter(Employee employee);
employee_id,last_name,email
last_name,email,gender,d_id
19.mybatis做模糊查询常用方法:
使用 ${...} 代替 #{...}
SELECT * FROM tableName WHERE name LIKE '%${text}%';
20.SQL标签抽取重用的SQL片段:
employee_id,last_name,email
last_name,email,gender,d_id
二、Mybatis进阶: