映射文件标签的使用
映射文件指导着MyBatis如何进行数据库增删改查, 有着非常重要的意义
映射语句示例
在接口中定义方法
public interface EmployeeMapper {
/**
* 通过id查询员工信息
* @param id
* @return
*/
Employee getEmpById(Integer id);
/**
* 增加员工信息
*@param employee
*/
void addEmp(Employee employee);
/**
* 通过id删除员工信息
* @param id
*/
void deleteEmpById(Integer id);
/**
* 修改员工信息
* @param employee
*/
void updateEmp(Employee employee);
}
select – 映射查询语句
<!--public Employee getEmpById(Integer id);-->
<!--resultType:返回值类型-->
<select id="getEmpById" resultType="emp" databaseId="mysql">
select * from tbl_employee where id = #{id}
</select>
因为每次测试都需要获取sqlSessionFactory对象,所以我将其封装成了一个私有方法
private SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
测试:
@Test
public void testMyBatis1() throws IOException {
//1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2、获取sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//4、调用接口中的方法
Employee employee = mapper.getEmpById(1);
//打印
System.out.println(employee);
} finally {
sqlSession.close();
}
}
select 返回List
在接口中定义方法
/**
* 获取所有的员工信息
* @return
*/
List<Employee> getAllEmps();
在映射文件中添加映射
<!--List<Employee> getAllEmps();-->
<!--resultType:如果返回的是一个集合,要写集合中的元素类型-->
<select id="getAllEmps" resultType="emp">
select * from tbl_employee
</select>
测试略
select 记录封装
返回一条数据并封装为Map
在接口中定义方法
/**
* 通过id查询员工信息,返回值为Map
*/
Map<String,Object> getEmpByIdReturnMap(Integer id);
在映射文件中添加映射
<!--Map<String,Object> getEmpByIdReturnMap(Integer id);-->
<select id="getEmpByIdReturnMap" resultType="map">
select * from tbl_employee where id = #{id}
</select>
测试略
返回多条数据并封装为Map<主键,类型>的形式
在接口中定义方法
/**
* 多条记录封装一个map:
* Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean
* @MapKey("id") 告诉mybatis封装这个map的使用id作为key
*/
@MapKey("id")
Map<Integer,Employee> getAllEmpsReturnMap();
在映射文件中添加映射
<!--Map<Integer,Employee> getAllEmpsReturnMap();-->
<select id="getAllEmpsReturnMap" resultType="emp">
select * from tbl_employee
</select>
测试略
insert – 映射插入语句
<!--public void addEmp(Employee employee);-->
<!-- parameterType:参数类型,可以省略 -->
<insert id="addEmp" parameterType="emp" databaseId="mysql">
insert into tbl_employee(`last_name`,`gender`,`email`) values (#{lastName},#{gender},#{email})
</insert>
测试:
@Test
public void testMyBatis2() throws IOException {
//1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2、获取sqlSession对象 ,不会自动提交数据
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee(null, "jake", "男", "jake@qd.com");
mapper.addEmp(employee);
sqlSession.commit();
} finally {
sqlSession.close();
}
}
insert 获取自增主键的值
<!--public void addEmp(Employee employee);-->
<!--
parameterType:参数类型,可以省略
获取自增主键的值:
mysql支持自增主键,自增主键的获取,mybatis也是利用statement.getGeneratedKeys()
useGeneratedKeys="true":使用自增主键获取主键值的策略
keyProperty:指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性
-->
<insert id="addEmp" parameterType="emp" databaseId="mysql"
useGeneratedKeys="true" keyProperty="id">
insert into tbl_employee(`last_name`,`gender`,`email`) values (#{lastName},#{gender},#{email})
</insert>
测试
@Test
public void testMyBatis3() throws IOException {
//1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2、获取sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee(null, "jake", "男", "jake@qd.com");
mapper.addEmp(employee);
sqlSession.commit();
System.out.println(employee.getId());
} finally {
sqlSession.close();
}
}
delete – 映射删除语句
<!--public void deleteEmpById(Integer id);-->
<delete id="deleteEmpById" databaseId="mysql">
delete from tbl_employee where id = #{id}
</delete>
测试:
@Test
public void testMyBatis3() throws IOException {
//1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2、获取sqlSession对象 不会自动提交数据
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//4、调用接口中的方法
mapper.deleteEmpById(2);
sqlSession.commit();
} finally {
sqlSession.close();
}
}
update – 映射更新语句
<!--public void updateEmp(Employee employee);-->
<update id="updateEmp" parameterType="emp" databaseId="mysql">
update tbl_employee
set `last_name` = #{lastName},`gender` = #{gender},`email` = #{email}
where id = #{id}
</update>
测试:
@Test
public void testMyBatis5() throws IOException {
//1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2、获取sqlSession对象 ,不会自动提交数据
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//4、调用接口中的方法
Employee employee = new Employee(1, "jake", "男", "jake@qd.com");
mapper.updateEmp(employee);
sqlSession.commit();
} finally {
sqlSession.close();
}
}
另外:
-
mybatis允许增删改直接定义以下类型返回值
void:无返回值
Integer、Long:返回操作的行数
Boolean:若操作行数为0,返回false,否则返回true
支持以上三种类型的基本类和包装类;
返回值类型直接定义在mapper接口的方法上即可,
不需要在映射文件中有多余的配置
如:/** * 修改员工信息 * @param employee */ Boolean updateEmp(Employee employee);
-
通过
sqlSessionFactory.openSession();
方式获取的sqlSession对象 ,我们需要手动提交数据
通过sqlSessionFactory.openSession(true);
方式获取的sqlSession对象 ,自动提交数据
参数处理
单个参数:mybatis不会做特殊处理,
#{参数名/任意名}
:取出参数值。
多个参数:mybatis会做特殊处理。
多个参数会被封装成 一个map,
key:param1…paramN,或者参数的索引也可以
value:传入的参数值
#{}
就是从map中获取指定的key的值;
异常:
org.apache.ibatis.binding.BindingException:
Parameter 'id' not found.
Available parameters are [1, 0, param1, param2]
操作:
方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
取值:#{id},#{lastName}
【命名参数】:明确指定封装参数时map的key;@Param("id")
多个参数会被封装成 一个map,
key:使用@Param
注解指定的值
value:参数值
#{指定的key}
取出对应的参数值
POJO:
如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;
#{属性名}
:取出传入的pojo的属性值
Map:
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
#{key}
:取出map中对应的值
TO:
如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)数据传输对象
Page{ int index; int size; }
思考
public Employee getEmp(@Param("id")Integer id,String lastName);
取值:id==>#{id/param1}
lastName==>#{param2}
public Employee getEmp(Integer id,@Param("e")Employee emp);
取值:id==>#{param1}
lastName===>#{param2.lastName/e.lastName}
##特别注意:如果是Collection(List、Set)
类型或者是数组,也会特殊处理。也是把传入的list或者数组封装在map中。
key:Collection(collection),如果是List还可以使用这个key(list)
数组(array)
public Employee getEmpById(List<Integer> ids);
取值:取出第一个id的值: #{list[0]}
总结
参数多时会封装map,为了不混乱,我们可以使用@Param来指定封装时使用的key;
#{key}就可以取出map中的值;
(@Param("id")Integer id,@Param("lastName")String lastName);
ParamNameResolver解析参数封装map的;
//1、names:{0=id, 1=lastName};构造器的时候就确定好了
确定流程:
- 获取每个标了param注解的参数的@Param的值:id,lastName; 赋值给name;
- 每次解析一个参数给map中保存信息:(key:参数索引,value:name的值)
name的值:
----标注了param注解:注解的值
----没有标注:
--------1.全局配置:useActualParamName(jdk1.8):name=参数名
--------2.name=map.size();相当于当前元素的索引
{0=id, 1=lastName,2=2}
参数值的获取
#{}
:可以获取map中的值或者pojo对象属性的值;
${}
:可以获取map中的值或者pojo对象属性的值;
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}
#{}:更丰富的用法:
规定参数的一些规则:
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"/>
resultMap – 自定义结果集映射
select resultMap:自定义结果集映射规则
<!--
自定义某个javaBean的封装规则
type:自定义规则的Java类型
id:唯一id方便使用
-->
<resultMap id="MyEmp" type="com.szm.mybatis.bean.Employee">
<!--指定主键列的封装规则
id定义主键会在底层有优化
column:指定哪一列
property:指定对应的JavaBean属性
-->
<id column="id" property="id"/>
<!--定义普通列的封装规则 -->
<result column="last_name" property="lastName"/>
<!--其他不指定的列会自动封装,但我们只要写resultMap就把全部的映射规则都写上-->
<result column="email" property="email" />
<result column="garden" property="garden" />
</resultMap>
<!--resultMap:自定义结果集映射规则-->
<!--Employee getEmpById(Integer id);-->
<select id="getEmpById" resultMap="MyEmp">
select * from tbl_employee where id = #{id}
</select>
测试略
select association关联查询
<!--
场景一:
查询Employee的同时查询员工对应的部门
Employee===Department
一个员工有与之对应的部门信息;
id last_name gender d_id did dept_name (private Department dept;)
-->
<!--
联合查询:级联属性封装结果集
-->
<resultMap type="com.szm.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.szm.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.szm.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>
select association分步查询
<!-- 使用association进行分步查询:
1、先按照员工id查询员工信息
2、根据查询员工信息中的d_id值去部门表查出部门信息
3、部门设置到员工中;
-->
<!-- id last_name email gender d_id -->
<resultMap type="com.szm.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.szm.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}
</select>
com.szm.mybatis.dao.DepartmentMapper.xml
<!--public Department getDeptById(Integer id); -->
<select id="getDeptById" resultType="com.szm.mybatis.bean.Department">
select id,dept_name departmentName from tbl_dept where id=#{id}
</select>
延迟加载
可以使用延迟加载(懒加载);(按需加载)
Employee==>Dept:
我们每次查询Employee对象的时候,都将一起查询出来。
部门信息在我们使用的时候再去查询;
分段查询的基础之上加上两个配置:
在全局配置文件中的settings标签中加上如下配置
<!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
select collection关联查询
<!--
场景二:
查询部门的时候将部门对应的所有员工信息也查询出来:
-->
<!--
public class Department {
private Integer id;
private String departmentName;
private List<Employee> emps;
did dept_name || eid last_name email gender
-->
<!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则 -->
<resultMap type="com.szm.mybatis.bean.Department" id="MyDept">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
<!--
collection定义关联集合类型的属性的封装规则
ofType:指定集合里面元素的类型
-->
<collection property="emps" ofType="com.szm.mybatis.bean.Employee">
<!-- 定义这个集合中元素的封装规则 -->
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</collection>
</resultMap>
<!-- public Department getDeptByIdPlus(Integer id); -->
<select id="getDeptByIdPlus" resultMap="MyDept">
SELECT d.id did,d.dept_name dept_name,
e.id eid,e.last_name last_name,e.email email,e.gender gender
FROM tbl_dept d
LEFT JOIN tbl_employee e
ON d.id=e.d_id
WHERE d.id=#{id}
</select>
select collection分步查询
<!-- collection:分段查询 -->
<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep">
<id column="id" property="id"/>
<id column="dept_name" property="departmentName"/>
<collection property="emps"
select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
column="{deptId=id}" fetchType="lazy"></collection>
</resultMap>
<!-- public Department getDeptByIdStep(Integer id); -->
<select id="getDeptByIdStep" resultMap="MyDeptStep">
select id,dept_name from tbl_dept where id=#{id}
</select>
<!-- 扩展:多列的值传递过去:
将多列的值封装map传递;
column="{key1=column1,key2=column2}"
fetchType="lazy":表示使用延迟加载;
- lazy:延迟
- eager:立即
-->
discriminator 鉴别器
<!-- <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>
<!-- public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpDis">
select * from tbl_employee where id=#{id}
</select>
dynamicSQL - 动态SQL
- 动态 SQL是MyBatis强大特性之一。极大的简化我们拼装 SQL的操作。
- 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处 理器相似。
- MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作。
- if:判断
- choose (when, otherwise):分支选择;带了break的swtich-case
- trim 字符串截取(where(封装查询条件), set(封装修改条件))
- foreach 遍历集合
if
<!--
if:判断
trim 字符串截取(where(封装查询条件))
-->
<!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
<!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
<select id="getEmpsByConditionIf" resultType="com.szm.mybatis.bean.Employee">
select * from tbl_employee
<!-- where -->
<where>
<!-- test:判断表达式(OGNL)
OGNL参照PPT或者官方文档。
c:if test
从参数中取值进行判断
遇见特殊符号应该去写转义字符:
&&:
-->
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null && lastName!=""">
and last_name like #{lastName}
</if>
<if test="email!=null and email.trim()!=""">
and email=#{email}
</if>
<!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
<if test="gender==0 or gender==1">
and gender=#{gender}
</if>
</where>
</select>
<!--public List<Employee> getEmpsByConditionTrim(Employee employee); -->
<select id="getEmpsByConditionTrim" resultType="com.szm.mybatis.bean.Employee">
select * from tbl_employee
<!-- 后面多出的and或者or where标签不能解决
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符
-->
<!-- 自定义字符串的截取规则 -->
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id=#{id} and
</if>
<if test="lastName!=null && lastName!=""">
last_name like #{lastName} and
</if>
<if test="email!=null and email.trim()!=""">
email=#{email} and
</if>
<!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
<if test="gender==0 or gender==1">
gender=#{gender}
</if>
</trim>
</select>
choose (when, otherwise)
<!--
choose (when, otherwise):分支选择;带了break的swtich-case
trim 字符串截取(set(封装修改条件))
-->
<!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
<select id="getEmpsByConditionChoose" resultType="com.szm.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>
<!--public void updateEmp(Employee employee); -->
<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>
foreach
<!--
foreach 遍历集合
-->
<!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids); -->
<select id="getEmpsByConditionForeach" resultType="com.szm.mybatis.bean.Employee">
select * from tbl_employee
<!--
collection:指定要遍历的集合:
这里的collection只能填list或者是map,如果想填ids,需要在参数上加@Param注解
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>
<!-- 批量保存 -->
<!--public void addEmps(@Param("emps")List<Employee> emps); -->
<!-- 方式一 -->
<!--MySQL下批量保存:可以foreach遍历 mysql支持values(),(),()语法-->
<insert id="addEmps">
insert into tbl_employee(last_name,email,gender,d_id)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>
<!-- 方式二 -->
<!-- 这种方式需要数据库连接属性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>
<!-- 方式一和方式二id相同,测试时分开测试 -->
两个内置参数和bind
<!-- 两个内置参数:
不只是方法传递过来的参数可以被用来判断,取值。。。
mybatis默认还有两个内置参数:
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装为一个map;_parameter就是代表这个map
_databaseId:如果配置了databaseIdProvider标签。
_databaseId就是代表当前数据库的别名oracle
-->
<!--public List<Employee> getEmpsTestInnerParameter(Employee employee); -->
<select id="getEmpsTestInnerParameter" resultType="com.szm.mybatis.bean.Employee">
<!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
<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 – 抽取可重用语句块。
<!--
抽取可重用的sql片段。方便后面引用
1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
2、include来引用已经抽取的sql:
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
include-property:取值的正确方式${prop},
#{不能使用这种方式}
-->
<sql id="insertColumn">
<if test="_databaseId=='mysql'">
last_name,email,gender,d_id
</if>
</sql>
<insert id="addEmps">
insert into tbl_employee(
<!-- 引用外部定义的sql -->
<include refid="insertColumn">
<property name="testColomn" value="abc"/>
</include>
)
values
<foreach collection="emps" item="emp" separator=",">
(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
</foreach>
</insert>