MyBatis进阶

所有代码

  • 学MyBatis时,练习的所有代码都在此了【MyBatis_Maven_Two】,我会尽可能的打上注释。
  • 使一个Maven项目,使用工具IDEA,使用MySQL数据库

输入参数和输出参数

传递简单类型参数

  • 使用#{}占位符,或者${}进行sql拼接。(order by id 必须使用${})
  • 如果传递多个简单类型,使用@Param注解实现
  • 注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。

传递pojo对象

  • #{}或者${}括号中的值为pojo实体类中的属性名称。

传递pojo包装的对象

  • 包装对象:Pojo类中的一个属性是另外一个pojo。
  • 例:QueryVo中放一个user对象属性。

传递map集合

  • map集合中
    • 注意:map的key要和sql中的占位符保持名字一致。

resultMap

  • resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名必须一致才可映射成功。
  • 如果sql查询字段名和pojo的属性名不一致,那么就取不到值,为空。
  • 解决方法:可以通过resultMap标签将字段名和属性名设置成一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
  • resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

其他方法

  • 使用<setting>标签,添加到mybatis的配置文件中,也可处理该问题。
  <settings>    
      <!--下划线转驼峰命名法,默认false-->    
      <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>

或者

  • <resultMap>表键中使用autoMapping="true"属性,将自动加载其他属性
    • <resultMap>中最少写一个属性,否则会报错。原因不明
  <resultMap id="user_order" type="User" autoMapping="true">
      <id property="id" column="id"></id>
      <!-- 其他属性可以不写,使用autoMapping自动将同名的属性和列映射在一块 -->
  </resultMap>

MyBatis类型解析

  • 第一:mybatis自动处理java.util.Date
  • 第二:mybatis自动识别1:0为true/false。数据库中存1/0,java中直接收true/false
  • 第三:parameterType 和 resultType 解析
    • parameterType类型:jdk8中基本类型+String :double,float,int,short,boolean,long,date,string
  • 原理:
    • 1>会类型字符转小写,TypeAliasRegistry初始化构造方法中注册了很多类型,先从中检查
    • 2>如果如上没有,则用Resources.classForName(string)通过反射得到类型(核心原理是 Class.forName()类加载)

类型转换器

  • 每当MyBatis设置参数到PrepareStatement或者从ResultSet结果集中取值时,就会用到TypeHandler来处理数据库类型与Java类型之间的转换。
  • MyBatis类型转换器适用于Java实体类中的类型和数据库中的类型不对应时。
  • 下图是默认的TypeHandler:

MyBatis

代码实现

  • 实现TypeHandler类
  • 在mybatis的配置文件中添加类型转换器
  • 代码项目中都有
  <!--全局注册类型转换器-->
  <typeHandlers>
      <typeHandler handler="com.xx.convert.AddressHandler" javaType="com.xx.pojo.Address" jdbcType="VARCHAR"></typeHandler>
  </typeHandlers>

动态sql(重点)

作用

  • 通过mybatis提供的各种标签方法实现动态拼接sql

标签

  • If标签
    • 注意字符串类型的数据需要做不等于空字符串校验。
    • 语法:
  <if test="条件">
  </if>
  • Where标签
    • 该标签自动添加where,同时处理SQL语句中第一and和or关键字
    • 语法:
  <where>
      <if test=''>
      </if>
  </where>
  • forEach标签
  • 该标签循环遍历解析数据
  • 例:改造QueryVo类,添加集合属性,并添加get、set方法。
  • 可以通过forEach解析拿到
  • 语法:
  <foreach collection="接收那个类型的数据" item="item" open="(" close=")" separator=",">
      #{item}
  </foreach>
  • 剩余标签
    • choose (when, otherwise)类似Java的switch语句
    • trim (是一个格式化的标记,可以完成set或者是where标记的功能)
    • set (update中的set)
    • 其他标签可以参考这个博客【YSOcean】,讲的很详细。

sql片段

  • Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
  • 语法:
  <sql id="xx">重复SQL语句</sql>
  <!--引用-->
  <include refid="xx"/>

关联查询

表之前的关系包括:一对一、一对多、多对多

一对一查询

  • 需求:查询所有订单信息,关联查询下单用户信息。
  • 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单
  • 使用sql语句:
    • SELECT o.id,o.user_id userId, o.number,o.createtime,o.note,u.username,u.address FROM orders o LEFT JOIN user u ON o.user_id = u.id

方法一:使用resultType

  • 使用resultType,改造订单pojo类,此pojo类中包括了订单信息和用户信息
  • 这样返回对象的时候,mybatis自动把用户信息也注入进来了
  • OrderUser类继承Order类后OrderUser类包括了Order类的所有字段,只需要定义用户的信息字段即可
  • 在UserMapper.xml添加sql,如下:
      <!-- 查询订单,同时包含用户数据 -->
      <select id="queryOrderUser" resultType="orderUser">
      SELECT o.id,o.user_id,userId,o.number,
      o.createtime,o.note,u.username,u.address
      FROM
      `order` o LEFT JOIN `user` u 
      ON o.user_id = u.id
      </select>
    
  • 定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单。

方法二:使用resultMap(推荐使用)

  • 使用resultMap,定义专门的resultMap用于映射一对一查询结果。
  • 改造pojo类
  • Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
  • 这里resultMap指定orderUserResultMap,如下:
  <resultMap type="order" id="orderUserResultMap">
  <id property="id" column="id" />
  <result property="userId" column="user_id" />
  <result property="number" column="number" />
  <result property="createtime" column="createtime" />
  <result property="note" column="note" />
  <!-- association :配置一对一属性 -->
  <!-- property:order里面的User属性名 -->
  <!-- javaType:属性类型 -->
  <association property="user" javaType="user">
      <!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->
      <id property="id" column="user_id" />
      <result property="username" column="username" />
      <result property="address" column="address" />
  </association>
  
  </resultMap>

一对多

  • 查询所有用户信息及用户关联的订单信息。
  • 用户信息和订单信息为一对多关系。
  • sql语句:
    • SELECT u.id,u.username,u.birthday,u.sex,
    • u.address,o.id oid,o.number,o.createtime,o.note
    • FROM user u
    • LEFT JOIN order o ON u.id = o.user_id
  • 修改pojo类,在User类中添加List<Orders> orders属性
  • UserMapper.xml映射文件中添加:
<resultMap type="user" id="userOrderResultMap">
	<id property="id" column="id" />
	<result property="username" column="username" />
	<result property="birthday" column="birthday" />
	<result property="sex" column="sex" />
	<result property="address" column="address" />

	<!-- 配置一对多的关系 -->
	<collection property="orders" javaType="list" ofType="order">
		<!-- 配置主键,是关联Order的唯一标识 -->
		<id property="id" column="oid" />
		<result property="number" column="number" />
		<result property="createtime" column="createtime" />
		<result property="note" column="note" />
	</collection>
</resultMap>

MyBatis的注解开发方式(了解)

  • 从MyBatis3开始,注解提供了一种简单的方式来实现简单映射语句,这种方式不会引入大量的开销。但是灵活性较差,不易扩展。
  • Mybatis常用注解对应的目标和标签如表所示:
注解 目标 对应的XML标签
@Select 方法 <select>
@Insert 方法 <insert>
@Update 方法 <update>
@Delete 方法 <delete>
@Param 参数
@SelectKey 方法 <selectKey>
@One 方法 <association>
@Many 方法 <collection>


转载请注明:Memory的博客 » 点击阅读原文

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦