Mybatis映射文件配置使用

MyBatis-映射文件

映射文件指导着MyBatis如何进行数据库增删改查, 有着非常重要的意义;

•cache             –命名空间的二级缓存配置 
•cache-ref         – 其他命名空间缓存配置的引用。 
•resultMap         – 自定义结果集映射
*parameterMap     – 已废弃!老式风格的参数映射 
•sql             –抽取可重用语句块。 
•insert             – 映射插入语句 
•update             – 映射更新语句
•delete         – 映射删除语句
•select             – 映射查询语句

## insert、update、delete元素

image-20200115130131842

细节

*1、mybatis允许增删改直接在接口方法定义以下类型返回值
Integer、Long、Boolean、void-等基本类型
*

2、我们需要手动提交数据
sqlSessionFactory.openSession();===》手动提交
sqlSessionFactory.openSession(true);===》自动提交

主键生成方式

若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上。

mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();useGeneratedKeys=”true”;使用自增主键获取主键值策略keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性

image-20200115130245040

而对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素: selectKey 元素将会首先运行,id 会被设置,然 后插入语句会被调用

keyProperty:查出的主键值封装给javaBean的哪个属性
order=”BEFORE”:当前sql在插入sql之前运行
AFTER:当前sql在插入sql之后运行
resultType:查出的数据的返回值类型

BEFORE运行顺序:
    先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
    在运行插入的sql;就可以取出id属性对应的值
AFTER运行顺序:
    先运行插入的sql(从序列中取出新值作为id);
    再运行selectKey查询id的sql;

image-20200115130339089

image-20200115130352566

参数(Parameters)传递

单个参数

– 可以接受基本类型,对象类型,集合类型的值。这种情况 MyBatis可直接使用这个参数,不需要经过任何处理。

*• 多个参数 *

– 任意多个参数,都会被MyBatis重新包装成一个Map传入。 Map的key是param1,param2,0,1…,值就是参数的值。 

• 命名参数

– 在接口中为参数使用@Param起一个名字,MyBatis就会将这些参数封 装进map中,key就是我们自己指定的名字 

• POJO

– 当这些参数属于我们业务POJO时,我们直接传递POJO 

• Map

– 我们也可以封装多个参数为map,直接传递

##特别注意:

如果是Collection(List、Set)类型或者是数组,也会特殊处理。也是把传入的list或者数组封装在map中。
key:collection(collection),如果是List还可以使用这个key(list)
数组(array)

public Employee getEmpById(List ids);取值:取出第一-个id的值:#{list[0]}

参数值的获取

select * from tbl_employee where id=${id} and last_name=#{lastName}
Preparing: select * from tbl_employee where id=2 and last_name=?
区别:
    #{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
    ${}:取出的值直接拼装在sql语句中;会有安全问题;
    大多情况下,我们去参数的值都应该去使用#{};

原生jdbc不支持占位符的地方我们就可以使用${}进行取值
比如分表、排序。。。;按照年份分表拆分
select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order}
原生JDBC不支持预编译的需要使用$

#{}:更丰富的用法:
规定参数的一些规则:
javaType、 jdbcType、 mode(存储过程)、 numericScale、
resultMap、 typeHandler、 jdbcTypeName、 expression(未来准备支持的功能);

jdbcType通常需要在某种特定的条件下被设置:
    在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错);

    JdbcType OTHER:无效的类型;因为mybatis对所有的null都映射的是原生Jdbc的OTHER类型,oracle不能正确处理;

    由于全局配置中:jdbcTypeForNull=OTHER;oracle不支持;两种办法
    1、#{email,jdbcType=OTHER};
    2、jdbcTypeForNull=NULL
        全局配置:<setting name="jdbcTypeForNull" value="NULL"/>

参数处理

• 参数也可以指定一个特殊的数据类型:

image-20200115134010614

– javaType 通常可以从参数对象中来去确定

– 如果 null 被当作值来传递,对于所有可能为空的列, jdbcType 需要被设置

– 对于数值类型,还可以设置小数点后保留的位数

– mode 属性允许指定 IN,OUT 或 INOUT 参数。如果参数 为 OUT 或 INOUT,参数对象属性的真实值将会被改变, 就像在获取输出参数时所期望的那样。

• 参数位置支持的属性

– javaType、jdbcType、mode、numericScale、 resultMap、typeHandler、jdbcTypeName、expression

• 实际上通常被设置的是: 可能为空的列名指定 jdbcType

• #{key}:获取参数的值,预编译到SQL中。安全。

• ${key}:获取参数的值,拼接到SQL中。有SQL注入问 题。ORDER BY ${name}

select元素

• Select元素来定义查询操作。

• Id:唯一标识符。

– 用来引用这条语句,需要和接口的方法名一致

• parameterType:参数类型。

– 可以不传,MyBatis会根据TypeHandler自动推断

• resultType:返回值类型。

– 别名或者全类名,如果返回的是集合,定义集合中元 素的类型。不能和resultMap同时使用

image-20200115143200639

image-20200115134256703

自动映射

• 1、全局setting设置

– autoMappingBehavior默认是PARTIAL,开启自动映射 的功能。唯一的要求是列名和javaBean属性名一致 
– 如果autoMappingBehavior设置为null则会取消自动映射 
– 数据库字段命名规范,POJO属性符合驼峰命名法,如 A_COLUMNaColumn,我们可以开启自动驼峰命名规 则映射功能,mapUnderscoreToCamelCase=true。

• 2、自定义resultMap,实现高级结果集映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?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.atguigu.mybatis.dao.EmployeeMapperPlus">

<!--自定义某个javaBean的封装规则
type:自定义规则的Java类型
id:唯一id方便引用
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp">
<!--指定主键列的封装规则
id定义主键会底层有优化;
column:指定哪一列
property:指定对应的javaBean属性
-->
<id column="id" property="id"/>
<!-- 定义普通列封装规则 -->
<result column="last_name" property="lastName"/>
<!-- 其他不指定的列会自动封装:我们只要写resultMap就把全部的映射规则都写上。 -->
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</resultMap>

<!-- resultMap:自定义结果集映射规则; -->
<!-- public Employee getEmpById(Integer id); -->
<select id="getEmpById" resultMap="MySimpleEmp">
select * from tbl_employee where id=#{id}
</select>

<!--
场景一:
查询Employee的同时查询员工对应的部门
Employee===Department
一个员工有与之对应的部门信息;
id last_name gender d_id did dept_name (private Department dept;)
-->


<!--
联合查询:级联属性封装结果集
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
</resultMap>


<!--
使用association定义关联的单个对象的封装规则;
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>

<!-- association可以指定联合的javaBean对象
property="dept":指定哪个属性是联合的对象
javaType:指定这个属性对象的类型[不能省略]
-->
<association property="dept" javaType="com.atguigu.mybatis.bean.Department">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
<!-- public Employee getEmpAndDept(Integer id);-->
<select id="getEmpAndDept" resultMap="MyDifEmp">
SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
WHERE e.d_id=d.id AND e.id=#{id}
</select>

<!-- 使用association进行分步查询:
1、先按照员工id查询员工信息
2、根据查询员工信息中的d_id值去部门表查出部门信息
3、部门设置到员工中;
-->

<!-- id last_name email gender d_id -->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<!-- association定义关联对象的封装规则
select:表明当前属性是调用select指定的方法查出的结果
column:指定将哪一列的值传给这个方法

流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
-->
<association property="dept"
select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id">
</association>
</resultMap>
<!-- public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
select * from tbl_employee where id=#{id}
<if test="_parameter!=null">
and 1=1
</if>
</select>

<!-- 可以使用延迟加载(懒加载);(按需加载)
Employee==>Dept:
我们每次查询Employee对象的时候,都将一起查询出来。
部门信息在我们使用的时候再去查询;
分段查询的基础之上加上两个配置:
-->
<!-- ==================association============================ -->

<!--
场景二:
查询部门的时候将部门对应的所有员工信息也查询出来:注释在DepartmentMapper.xml中
-->
<!-- public List<Employee> getEmpsByDeptId(Integer deptId); -->
<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
select * from tbl_employee where d_id=#{deptId}
</select>



<!-- =======================鉴别器============================ -->
<!-- <discriminator javaType=""></discriminator>
鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为
封装Employee:
如果查出的是女生:就把部门信息查询出来,否则不查询;
如果是男生,把last_name这一列的值赋值给email;
-->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<!--
column:指定判定的列名
javaType:列值对应的java类型 -->
<discriminator javaType="string" column="gender">
<!--女生 resultType:指定封装的结果类型;不能缺少。/resultMap-->
<case value="0" resultType="com.atguigu.mybatis.bean.Employee">
<association property="dept"
select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id">
</association>
</case>
<!--男生 ;如果是男生,把last_name这一列的值赋值给email; -->
<case value="1" resultType="com.atguigu.mybatis.bean.Employee">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="last_name" property="email"/>
<result column="gender" property="gender"/>
</case>
</discriminator>
</resultMap>
</mapper>