Mybatis复习笔记3:映射文件详解

映射文件详解

参数处理(#和$的区别)

  • #{}:可以获取map中的值或者实体对象属性的值;
  • ${}:可以获取map中的值或者实体对象属性的值;
select * from person where id=${id} and name=#{name}
# 控制台输出:select * from person where id=2 and last_name=?

区别

  • #{}:是以预编译的形式,将参数设置到SQL语句中,相当于JDBC中的 PreparedStatement;可以防止SQL注入;
  • ${}:取出的值直接拼接在SQL语句中;会有安全问题;

大多情况下,我们取参数的值都应该去使用 #{} ;

原生 JDBC 不支持占位符的地方我们就可以使用 ${} 进行取值
比如分表、排序等;

# 按照年份分表拆分
select * from ${year}_income where xxx;

#{}更丰富的用法

规定参数的一些规则:
javaType、 jdbcType、 mode(存储过程)、 numericScale、
resultMap、 typeHandler、 jdbcTypeName

jdbcType通常需要在某种特定的条件下被设置:
在我们数据为null的时候,有些数据库可能不能识别 MyBatis 对 NULL 的默认处理。比如Oracle(报错,JdbcType OTHER:无效的类型);
因为 MyBatis 对所有的 NULL 都映射的是原生 JDBC 的 OTHER 类型,Oracle 不能正确处理;
由于全局配置中:jdbcTypeForNull=OTHER;而Oracle不支持OTHER类型;

两种解决办法:
1、给#{}中加上javaType,如:

<insert id="addPer" databaseId="oracle">
	<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
		select PERSON_SEQ.nextval from dual 
	</selectKey>
	insert into person(id,name,age,email) 
	values(#{id},#{name},#{age},#{email,jdbcType=NULL})
</insert>

2、在配置文件的settings标签中设置 jdbcTypeForNull=NULL,如:

<settings>
	<setting name="jdbcTypeForNull" value="NULL"/>
</settings>

parameterType参数类型

parameterType为输入参数,即负责配置的时候传入的参数类型。
parameterType有基本数据类型和复杂的数据类型配置

基本数据类型

基本数据类型:int,String,long,Date等;
这是在我之前的博客中讲的最多的了

<select id="findByType" parameterType="String" resultType="com.domain.User">
        select * from product where product_type like #{product_type}
</select>

复杂数据类型

复杂数据类型:Java实体类和Map
博主暂时只遇到Java实体类的情况,所以就先讲实体类的情况先

传入类型为实体类

这种使用方式广泛应用于实际开发中,由多个对象组成一个查询条件来实现数据的查询。

<select id="findUserByVo" parameterType="com.domain.QueryVo" resultType="com.domain.User">
        select * from product where product_type like #{user.product_type}
</select>

QueryVo是我们新建的一个类,如下:

package com.domain;

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

我们可以看到,该类中的参数为User类型的,所以xml中的写法变为"#{user.product_type}"

测试类如下:

    /**
     * 测试QueryVo作为查询条件
     */
    @Test
    public void testfindByVo(){
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setProduct_type("%用品%");
        vo.setUser(user);
        List<User>userList = userDao.findUserByVo(vo);
        for (User user1:userList){
            System.out.println(user1);
        }
    }

resultMap结果映射

resultMap标签一般用于对实体类的封装,即将实体类中的字段与数据库表中的字段进行关联映射

用法:

<resultMap id="自定义ID名" type="实体类" >
	<!--主键字段的对应如下-->
	<id property="实体类属性" column="数据库主键字段名"/>
	<!--非主键字段的对应如下-->
	<result property="实体类属性" column="数据库字段名" jdbcType="数据库字段类型(可不写)"/>
</resultMap>

如:
1.当实体类中的字段与数据库表中的字段不相同时,在resultMap标签中将实体类字段与数据库字段进行关联映射

<resultMap id="userMap" type="com.domain.User">
        <result property="name" column="product_name"/>
        <result property="type" column="product_type"/>
        <result property="price" column="product_price"/>
        <result property="date" column="regist_date"/>
</resultMap>

2.多表操作中的一对一关联查询

<resultMap id="accountUserMap" type="account">
        <id property="id" column="aid"/>    <!--此处的aid为表中id的别名-->
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <association property="user" javaType="user">
            <id property="id" column="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
        </association>
</resultMap>

注:这里association标签的作用是将account和user两张表关联起来再映射到实体类上。

3.多表操作中的一对多操作

    <!-- 定义User的resultMap-->
    <!--一对多查询-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account">   <!--ofType指的是集合accounts的类型-->
            <id column="aid" property="id"/>    <!--aid为列别名,起别名是因为主子表都有该字段-->
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
        </collection>
    </resultMap>

上面嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则。

association关联

  • association 可以指定联合的 javaBean 对象
    property=“user”:指定哪个属性是联合的对象
    javaType:指定这个属性对象的类型(不能省略)
<resultMap id="accountUserMap" type="account">
        <id property="id" column="aid"/>    <!--此处的aid为表中id的别名-->
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <association property="user" javaType="user">
            <id property="id" column="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
        </association>
</resultMap>
  • association 定义关联对象的封装规则
    select:表明当前属性是调用 select 指定的方法查出的结果
    column:指定将哪一列的值传给这个方法
<resultMap type="com.domain.User" id="MyPerByStep">
	 <id column="id" property="id"/>
	 <result column="name" property="name"/>
	 <result column="email" property="email"/>
	 <result column="age" property="sex"/>
	 <!-- association定义关联对象的封装规则
	 	select:表明当前属性是调用select指定的方法查出的结果
	 	column:指定将哪一列的值传给这个方法	
	 	流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
	 -->
 	<association property="comp" 
 		select="com.dao.CompanyMapper.getCompById"
 		column="id">
 	</association>
</resultMap>

流程:使用select指定的方法(传入 column 指定的这列参数的值)查出对象,并封装给 property 指定的属性

discriminator鉴别器

MyBatis可以使用 discriminator 判断某列的值,然后根据某列的值改变封装行为
有时候,一个数据库查询可能会返回多个不同的结果集(但总体上还是有一定的联系的)。
鉴别器(discriminator)标签就是被设计来应对这种情况的,另外也能处理其它情况,例如类的继承层次结构。 鉴别器的概念很好理解——它很像 Java 中的 switch 语句

一个鉴别器的定义需要指定 column 和 javaType 属性。column 指定了 MyBatis 查询被比较值的地方。 而 javaType 用来确保使用正确的相等测试(虽然很多情况下字符串的相等测试都可以工作)。

例如:
封装Person
如果查出的是女生:就把公司信息查询出来,否则不查询;
如果是男生,把 name 这一列的值赋值给 email;

<resultMap type="com.domain.User" id="MyEmpDis">
	 <id column="id" property="id"/>
	 <result column="name" property="name"/>
	 <result column="email" property="email"/>
	 <result column="sex" property="sex"/>
	 <!--
	 	column:指定判定的列名
	 	javaType:列值对应的java类型  
	 -->
	 <discriminator javaType="string" column="sex">
	 	<!--女生  resultType:指定封装的结果类型;不能缺少。/resultMap-->
	 	<case value="0" resultType="com.domain.User">
	 		<association property="comp"
			 	select="com.dao.CompanyMapper.getCompById"
			 	column="id">
		 	</association>
	 	</case>
	 	<!--男生  如果是男生,把name这一列的值赋值给email; -->
	 	<case value="1" resultType="com.domain.User">
		 	<id column="id" property="id"/>
			 <result column="name" property="name"/>
			 <result column="name" property="email"/>
			 <result column="sex" property="sex"/>
	 	</case>
	 </discriminator>
</resultMap>

在这个示例中,MyBatis 会从结果集中得到每条记录,然后比较它的 sex 的值。 如果它匹配任意一个鉴别器的 case,就会使用这个 case 指定的结果映射。 这个过程是互斥的,也就是说,剩余的结果映射将被忽略。 如果不能匹配任何一个 case,MyBatis 就只会使用鉴别器块外定义的结果映射。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值