MyBatis映射文件

映射文件标签的使用

映射文件指导着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();
    }
}

另外:

  1. mybatis允许增删改直接定义以下类型返回值
    void:无返回值
    Integer、Long:返回操作的行数
    Boolean:若操作行数为0,返回false,否则返回true
    支持以上三种类型的基本类和包装类;
    返回值类型直接定义在mapper接口的方法上即可,
    不需要在映射文件中有多余的配置
    如:

    /**
    * 修改员工信息
    * @param employee
    */    
    Boolean updateEmp(Employee employee);
    
    
  2. 通过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};构造器的时候就确定好了

确定流程:

  1. 获取每个标了param注解的参数的@Param的值:id,lastName; 赋值给name;
  2. 每次解析一个参数给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 &amp;&amp; lastName!=&quot;&quot;">
		 		and last_name like #{lastName}
		 	</if>
		 	<if test="email!=null and email.trim()!=&quot;&quot;">
		 		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 &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>
	 </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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值