MyBatis 学习(七):深入 Mapper XML映射文件

一、Mapper XML映射文件

MyBatis 的真正强大之处在于它的映射语句,这也是它的魔力所在。由于它的功能异常强大,映射器XML文件就显得相对简单。

SQL映射文件常用的元素如下:

  • select 映射查询语句
  • insert 映射插入语句
  • update 映射更新语句
  • delete 映射删除语句
  • sql 可被其他语句引用的可重用语句块
  • cache 给定命名空间的缓存配置
  • cache-ref 其他命名空间缓存配置的引用
  • resultMap 最复杂也是最强大的元素,用来描述如何从数据库结果集中加载对象

二、select 查询语句

在 SQL 映射文件中 元素用于映射 SQL 的 select 语句,其示例代码如下:

<select id="selectUserById" parameterType="Integer" resultType="com.zhang.pojo.User">
	select * from user where id = #{id}
</select>

在上述代码中,这个语句被称作 selectUserById,其 id 值是唯一标识符,它接受一个 Integer 类型 的参数,返回一个 User 类型 的对象,结果集自动映射到 User 属性。

注意: 参数符号 #{id},这是告诉 MyBatis 创建一个预处理语句参数。通过JDBC,这样的一个参数在 SQL 中会由一个 “?” 来标识,并被传递到一个新的预处理语句中。以上配置文件执行时会生成如下JDBC代码。

String selectUserById = "select * from user where id = ?";
PreparedStatement ps = conn.prepareStatement(selectUserById);
ps.setInt(1,id);

还有一种 ${id},这种是字符串替换,在动态 SQL 解析阶段将会进行变量替换。

使用#{}可以有效的防止SQL注入,提高系统安全性。

< select> 元素除了有上述示例代码中的几个属性以外,还有一些常用的属性,如下表 所示。

属性名称描述
id它和 Mapper 的命名空间组合起来使用,是唯一标识符,可以被用来引用这条语句
parameterType表示传入 SQL 语句的参数类型的全限定名或别名。它是一个可选属性,MyBatis 能推断出具体传入语句的参数
resultTypeSQL 语句执行后返回的类型(全限定名或者别名)。如果是集合类型,返回的是集合元素的类型,返回时可以使用 resultType 或 resultMap 之一
resultMap外部 resultMap 的命名引用。返回时可以使用 resultType 或 resultMap 之一
flushCache用于设置在调用 SQL 语句后是否要求 MyBatis 清空之前查询的本地缓存和二级缓存,默认值为 false,如果设置为 true,则任何时候只要 SQL 语句被调用都将清空本地缓存和二级缓存
useCache启动二级缓存的开关,默认值为 true,表示将査询结果存入二级缓存中
timeout用于设置超时参数,单位是秒(s),超时将抛出异常
fetchSize获取记录的总条数设定
statementType告诉 MyBatis 使用哪个 JDBC 的 Statement 工作,取值为 STATEMENT(Statement)、 PREPARED(PreparedStatement)、CALLABLE(CallableStatement)
resultSetType这是针对 JDBC 的 ResultSet 接口而言,其值可设置为 FORWARD_ONLY(只允许向前访问)、SCROLL_SENSITIVE(双向滚动,但不及时更新)、SCROLLJNSENSITIVE(双向滚动,及时更新)

三、insert、update 和 delete

insert、update 和 delete 元素用来映射 DML 语句,是MyBatis 中常用的元素之一。

insert、update 和 delete 元素配置和 select 非常接近,但是也有它们的特有属性:

  • useGeneratedKeys: (仅对 insert 和 update 有用) 这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来获取有数据库内部生成的主键(比如,像 MySQL 和 SQL Server 这样的关系数据库系统的自动递增字段),默认值为 false。
  • keyProperty:(仅对 insert 和 update 有用) 唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认为 unset。如果是联合主键,可以将多个值用逗号分隔开。
  • keyColumn:(仅对 insert 和 update 有用) 该属性用于设置第几列是主键,当主键列不是表中的第 1 列时需要设置。如果是联合主键,可以将多个值用逗号隔开。

1)主键(自动递增)回填

MySQL、SQL Server 等数据库的表格可以采用自动递增的字段作为主键,有时可能需要使用这个刚刚产生的主键,用于关联其他业务。

首先为 com.zhang.mapper 包中的 SQL 映射文件 UserMapper.xml 中 id 为 insertUser 的 < insert> 元素添加 keyPropertyuseGeneratedKeys 属性,具体代码如下:

<!--添加一个用户,成功后将主键值返回填给id(user的属性)-->
<insert id="insertUser" parameterType="com.zhang.pojo.User" keyProperty="id" useGeneratedKeys="true">
	insert into user(id,name,sex,age) values(default,#{name},#{sex},#{age})
</insert>

然后再 com.zhang.work 包的 MainApp 类进行调用,具体代码如下:

User user = new User();
user.setName("小明");
user.setSex("男");
user.setAge(20);

int add = userService.addUser(user);

System.out.println("添加了" + add + "条记录");
System.out.println("添加记录的主键是" + user.getId());

2)自定义主键

如果在实际工程中使用的数据库不支持主键自动递增(例如 Oracle),或者取消了主键自动递增的规则,可以使用 MyBatis 的 < selectKey> 元素来自定义生成主键。具体配置示例代码如下:

<!-- 添加一个用户,#{uname}为 com.mybatis.po.MyUser 的属性值 -->
<insert id="insertUser" parameterType="com.po.MyUser">
    <!-- 先使用selectKey元素定义主键,然后再定义SQL语句 -->
    <selectKey keyProperty="uid" resultType="Integer" order="BEFORE">
    select if(max(uid) is null,1,max(uid)+1) as newUid from user)
    </selectKey>
    insert into user (uid,uname,usex) values(#{uid},#{uname},#{usex})
</insert>

在执行上述示例代码时,< selectKey> 元素首先被执行,该元素通过自定义的语句设置数据表的主键,然后执行插入语句。

< selectKey> 元素的 keyProperty 属性指定了新生主键值返回给 PO 类(com.po.MyUser)的哪个属性。

  • order 属性可以设置为 BEFORE 或 AFTER。BEFORE 表示先执行 元素然后执行插入语句。AFTER 表示先执行插入语句再执行 元素。

insert、update 和 delete 语句的示例:

<!--添加一个用户-->
<insert id="insertUser" parameterType="com.zhang.pojo.User" >
	insert into user(id,name,sex,age) values(default,#{name},#{sex},#{age})
</insert>

<!--修改一个用户-->
<update id="updateUser" parameterType="com.zhang.pojo.User">
	updare user set name = #{name},sex = #{sex},age = age + 1 where id = #{id}
</update>

<!--删除一个用户-->
<delete id="deleteUser" parameterType="Integer">
	delete from user where id = #{id}
</delete>

四、sql 元素

< sql> 元素的作用在于可以定义 SQL 语句的一部分(代码片段),以方便后面的 SQL 语句引用它,例如反复使用的列名。

MyBatis中sql标签与include标签进行配合,灵活的查询需要的数据。

<sql id="ref">
    id,name,sex,age
</sql>

<select id="selectUserById" resultType="com.zhang.pojo.User">
    select
    <include refid="ref"/>
    from
    user where id = #{id}
</select>

sql 标签中 id属性 对应 include标签 中的 refid属性 。通过include标签将sql片段和原sql片段进行拼接成一个完成的sql语句进行执行。

include标签 中还可以用 property标签,用以指定自定义属性。


<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>

<select id="selectUser" resultType="map">
  select
    <include refid="userColumns"><property name="alias" value="u1"/></include>,
    <include refid="userColumns"><property name="alias" value="u2"/></include>
  from user u1
    cross join user u2
</select>

在sql标签中通过${}取出对应include标签中设置的属性值。

五、参数(Parameters)

  • 简单参数映射

    原生的类型或者简单数据类型(比如整形和字符串),因为没有相关属性,它会完全用参数值来代替。例如:

    <select id="selectUserById" parametersType="Intager" resultType="com.zhang.pojo.User">
    	select * from user where id = #{id}
    </select>
    
  • 对象参数映射

    如果传入一个复杂对象(比如 User),行为就有点不同了。例如:

    <insert id="insertUser" parametersType="com.zhang.pojo.User">
    	insert into user values(default,#{name},#{sex},#{age})
    </insert>
    

    如果User类型的参数对象被传递到了语句中,如 #{name} 语句则会查找参数对象User 的 name 属性,#{sex},#{age}也是一样,然后将它们的值传入预处理语句的参数中。

  • 多个参数映射

    • 利用 #{参数顺序} 接收参数

      mapper 层的函数方法

      public List<Student> selStudentBySex(String sex,Intager pageNumber);
      

      对应的 xml 文件

      <select id="selStudentBySex" resultType="com.zhang.pojo.Student">
      	select * from student where sex=#{0} limit #{1},5
      </select>
      

      其中,#{0}代表接收的是mapper层中的第一个参数,#{1}代表接收的是mapper层中的第二个参数,更多参数依次往后加即可。

    • 利用 Map 传递多个参数
      mapper 层的函数方法

      public List<Student> selStudentBySex(Map paramMap);
      

      service 实现类的函数方法

      Map<String,Object> map = new HashMap<String, Object>();
      map.put("sex","男");
      map.put("pageNumber",0);
      List<Student> studentList = studentService.findStudentBySex(map);
      

      对应的 xml 文件

      <select id="selStudentBySex" resultType="com.zhang.pojo.Student">
      	select * from student where sex=#{sex} limit #{pageNumber},5
      </select>
      

      这种方法不太直观,无法从接口看到传递的参数类型。

    • 利用注解@param() 传递多个参数(推荐使用)

      mapper 层的函数方法

      public List<Student> selStudentBySex(@Param("sex")String sex,@Param("pageNumber")Integer pageNumber);
      

      对应的 xml 文件

      <select id="selStudentBySex" resultType="com.zhang.pojo.Student">
      	select * from student where sex=#{sex} limit #{pageNumber},5
      </select>
      

      如果多个参数中又一个复杂对象参数该怎么办?

      mapper 层的函数方法

      public List<Student> selStudentBySex(@Param("student")Student student,@Param("pageNumber")Integer pageNumber);
      

      对应的 xml 文件

      <select id="selStudentBySex" resultType="com.zhang.pojo.Student">
      	select * from student where sex=#{student.sex} limit #{pageNumber},5
      </select>
      

      在 xml 文件中 使用 @Param 注解里的对象的属性即可,#{student.sex}

参考文章:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值