目录
在SQL映射文件中,只需根据MyBatis提供的标签写入SQL语句操作, 将SQL语句从程序的代码中分离出来,对JDBC访问数据库的代码进行封装,只需关注sql事务操作。
以下是SQL映射文件中的部分常用元素
- "1.0" encoding="UTF-8"?>
- mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="dao.SysUserMapper">
-
- <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
-
- <insert>insert>
-
- <update>update>
-
- <select>select>
-
- <delete>delete>
-
- <resultMap>resultMap>
- ......
- mapper>
- sql语句中的#{} 代表一个占位符,可根据key 找到值
- 查询一个条件的值时,不需写key 标识对应 如: Param, 一个参数时MyBtais会自动找到。
- Mapper 接口
- /**
- * 模糊查询用户姓名
- */
- List
getLikeAllUser(String name);
- Mapper.xml 映射文件
- <select id="getLikeAllUser" resultType="user">
- --模糊查询用户表里的名称
- select * from user where username like CONCAT("%",#{username},"%")
- select>
- Mapper 接口
- /**
- * 多条件模糊查询用户姓名
- */
- List
getLikesAllUser(User user);
- Mapper.xml 映射文件
- <select id="getLikesAllUser" resultType="user" parameterType="user">
- select id,name,password from user where name like CONCAT("%",#{name},"%") and id=#{id}
- select>
- 直接根据map 的key 来找值
- /**
- * 根据Map 来查询用户信息
- */
- List
getLikeUserByMap(Map map) ;
- <select id="getLikeUserByMap" resultType="cn.bdqn.entity.User">
- select id,name,password from user where name like CONCAT(#{name},"%") and password=#{password}
- select>
- 没使用@Param注解多参数查询前,遇到的问题:
- /**
- * 根据两个参数条件查询用户信息
- */
- List
getLikeUsersNoByParam(String name,String password);
- <select id="getLikeUsersNoByParam" resultType="user">
- select id,name,password from user where name like CONCAT(#{name},"%") and password=#{password}
- select>
- 上述代码执行结果:
该代码出现异常,指定没有找到key .
报错原因:由于是多个参数传值,底层是key-value形式,而java编译时会将sql里的name,password转译成 [arg1,arg0,param1,param2],只限于JDK1.8中。如果不将key设置成底层格式,如param1,他就会找不到参数的顺序,所以会报错。
- 使用@param注解设置key 会自动跟sql里的key 进行匹配,顺序更好查找。
- /**
- * @param注解来查找用户信息
- */
- List
getLikeUsersByParam(@Param("name") String name,@Param("password") String password); -
-
- /**
- * 将@Param作为实体类的key查找
- */
- List
getLikeUsersByJOUO(@Param("user") User user);
- @Param将实体类作为key时,sql中要通过它的key . 出来值
- <select id="getLikeUsersByParam" resultType="cn.bdqn.entity.User">
- select id,name,password from user where name like CONCAT(#{name},"%") and password=#{password}
- select>
-
- <select id="getLikeUsersByJOUO" resultType="cn.bdqn.entity.User">
- select id,name,password from user where name like CONCAT(#{user.name},"%") and password=#{user.password}
-
- select>
- 实现多参数时,也可以使用底层顺序,但是sql中的值必须跟底层名称一样,如: param1,param2,一定要注意参数顺序。
- <select id="getLikeUsers" resultType="cn.bdqn.entity.User">
- select id,name,password from user where name like CONCAT(#{param1},"%") and password=#{param2}
- select>
- MyBtais SQL映射文件查找时,必须返回一个resultType的类型去接收,最后自动映射,但是自动映射的前提为: 实体类属性与数据库字段名称一致。但是,按照阿里巴巴开发规约的规定,数据库不允许出现大写字母,两个字母中间使用_连接这种情况下建议使用resultMap进行自定义映射。
- 当数据库字段和实体类属性名称不一致时或返回多个实体类时,可以使用resultMap自定义结果映射。
- 当没有设置剩下的属性时,他们可以自动映射,前提是名称一致。
- <resultMap id="userIdCard" type="user">
- <id property="id" column="id">id>
- <result property="idCard" column="id_card">result>
- resultMap>
- <select id="getResultMapTest" resultMap="userIdCard">
- select * from user
- select>
注意:
- association 嵌套结果映射适用于多个实体类查询时,并且实体类对应的关系是,一对一,多对一。
- 一对一: 如: 一个学生只属于一个班级
- 多对一: 多个学生都属于一个班级
- Student 实体类中定义Class班级
-
- public class User implements Serializable {
- private Integer id;
- private String name;
- private String password;
- //将班级类定义为成员变量(一个实体对象)
- private ClassInfo classInfo;
-
- //...省略get set 方法...
-
- }
- resultMap 写法
- <resultMap id="getStudentsByClassInfo" type="student">
- <id property="id" column="id">id>
- <result property="name" column="name">result>
-
- <association property="classInfo" javaType="classInfo">
- <id property="classId" column="class_id">id>
- <result property="calssName" column="class_name">result>
- association>
- resultMap>
- <select id="getStudentsByClassInfo" resultMap="getStudentsByClassInfo">
- select u.name,c.class_name from student u left join classinfo c on u.class_id=c.class_id
- select>
- collection 嵌套结果映射 适用于 实体类是一对多的关系。
- 一对多: 如: 一个班里有多个学生,对应实体类中也就是一个班级类里有多个学生实体对象(使用集合)。
- ClassInfo实体类中定义studentList集合
- /**
- * 班级实体类
- */
- public class ClassInfo {
-
- private Integer classId;
- private String calssName;
- //定义学生集合
- private List
userList; -
- //...get set 方法已省略
-
- }
- resultMap 写法
- <resultMap id="getStudentsByClassInfo" type="classInfo">
- <id property="classId" column="class_Id">id>
- <id property="calssName" column="class_Name">id>
-
- <collection property="studentList" ofType="student">
- <id property="id" column="id">id>
- <id property="name" column="name">id>
- collection>
- resultMap>
- <select id="getAllStudentsByClassInfo" resultMap="getStudentsByClassInfo">
- select u.name,c.class_name from classinfo c left join student u on c.class_id=u.class_id
- where c.class_id=#{calssId}
- select>
注意:association 和 collction 的写法差别 : collction 需要设置一个 ofType 集合对象的属性类型。
两者的映射行为:
Mybtais中是开启自动映射的,默认为 PARTIAL。
- <setting name="autoMappingBehavior" value="RARTIAL"/>
- ## insert
- parameterType 参数类型: 实体类或map或其他(可使用别名)
- <insert id="add" parameterType="user"> insert>
- ## update
- <update id="update" parameterType="user"> update>
- ## delete
- <delete id="delete" parameterType="user"> delete>
注意:增删改(insert、update、delete)这类操作通常返回影响行数,这三种元素均没有resultType/resultMap属性。
- 当处理SQL与语句时,当一个字段出现为null的情况,也会影响另一个条件的查询,可以使用动态处理SQL语句,让sql语句更加的灵活。
- where 标签的主要作用是对sql 语句中的where 关键字进行简化处理,并可以智能处理其内部and,or 关键字,避免多余的语法错误。
- 当where 里的条件语句都为false时,where 标签就不会进行一个拼接。
- <select id="getUsers" resultType="cn.bdqn.entity.User">
- select id,name,password from user
- <where>
- <if test="user.name!=null">
- name like CONCAT(#{user.name},"%")
- if>
- <if test="password!=null">
- and password=#{user.password}
- if>
- where>
- select>
如果没加where 标签,当其中一个条件字段为null时,sql 语法就会出现错误,当加上where 标签之后,即使有一个字段为null也会自动把多余关键字给去掉。
- choose标签其实就是java中的switch, choose 标签里有when,otherwise这两个子标签,而choose就相当于switch,when==case+break,otherwise==default。
- 该标签的条件是唯一的,只要一个条件满足就会终止。
- <select id="selectUsers" resultType="user">
- select id,name,password from t_supplier
- <where>
- <choose>
- <when test="name!=null and name!=''">
- name=#{name}
- when>
- <when test="password!=null and password!=''">
- supCode=#{supCode}
- when>
- <otherwise>
- id=#{id}
- otherwise>
-
- choose>
- <where>
- select>
- 该标签一般用于循环某个多条件的sql语句,提高效率。
- sql中可以遍历的类型参数: List,Map,array
- /**
- * 根据角色ID集合查询用户列表新信息
- * @param roleList
- * @return
- */
- List
getUserByRoleIdList(List roleList) ;
- <select id="getUserByRoleIdList" resultType="entity.SysUser">
- select * from t_sys_user where roleId in
- <foreach collection="list" item="item" open="(" separator="," close=")">
- #{item}
- foreach>
- select>
collection=“” 引号中一般为入参@Param引号中的值 或默认值
item=“” 相当于给集合中每个元素都起了一个别名
open=“” 循环开始需要放一个什么字符串
separator=“” 第一次循环结束后需要用什么分割符拼接第二次循环结果
close=“” 全部循环完之后需要加什么
- set 标签出现在update标签的修改语句中,它会动态在sql语句中添加set关键字,并添加一些属性。
- <update id="update">
- update user
- <set>
- <if test="name!=null and name!=''">
- supName=#{supName},
- if>
- <if test="password!=null and password!=''">
- supDesc=#{supDesc},
- if>
- set>
- <where>
- id=#{id}
- where>
- update>
注意
- 修改时需要根据业务判断使用set标签就可以还是需要set+if标签。
- 如果使用set 那么当其中某一个字段为null时也会随之更改。
- 使用trim 标签一样可以实现 where 和 set 标签的动态忽略前后缀,但trim标签比set 标签范围更广,它可以给各种标签添加和忽略前后缀。
- <update id="update">
- update user
- <trim prefix="set" suffix="where id=#{id}" suffixOverrides="," >
- <if test="name!=null and name!=''">
- name=#{name},
- if>
- <if test="password!=null and password!=''">
- password=#{password},
- if>
- trim>
- update>
1.prefix :如果trim标签中有一个条件成立的话 就会在最前面添加prefix里面配置的关键字。
2.prefixOverrides :如果前面没有条件成立的话,会动态去掉前面的and关键字或者or关键字或其他,如果前面又条件成立的话,不会去掉所配置的关键字。
3.suffixOverrides 如果后面没有条件成立的话会动态去掉每个条件后面跟着的该关键字
4.suffix 如果trim标签中有一个条件成立的话,就会在所有成立的条件最后加上suffix配置的关键字,如果没有一个条件成立则不会加上所配置的关键字。