MyBatis的XxxMapper.xml 映射器的详解(六)

年轻的时候,遇见了那个人,便以为余生再没有江湖,后来,才发现,她才是江湖的起源。

上一章简单介绍了MyBatis的核心配置文件 SqlMapConfig.xml(五),如果没有看过,请观看上一章

一 . XxxMapper.xml 映射器的使用

在MyBatis 中,将Dao层的接口与对应的Mapper.xml 配置文件进行组合使用,而不是以前的接口实现类处理。 这里着重讲解一下,这个配置文件的使用。 将XxxMapper.xml 放置在与接口XxxMapper.java 同级的目录下。

一.一 Schema约束

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

当然,前面不要忘记 xml文件的头部。


<?xml version="1.0" encoding="UTF-8"?>

一.二 Mapper 根节点

有一个根节点,是mapper, 里面只有一个属性, namespace, 命名空间。 后面跟的值一般为其所在的包路径,或者说是XxxMapper.java 接口所在的包路径。

<mapper namespace="com.yjl.mapper.UserMapper" >

一.三 下属节点

在根节点 mapper 下的节点有:

  1. select       最常用,最复杂的元素之一, 可以自定义参数,返回结果集。
  2. insert        插入语句 返回所影响的行数
  3. update        更新语句 返回所影响的行数
  4. delete        删除语句 返回所影响的行数
  5. sql        定义一部分sql,构成sql 片段,然后在各个语句中引用。
  6. resultMap        从结果集中来加载对象,最复杂也是最强大的元素,提供了映射的规则。
  7. cache        给定命名空间的缓存配置
  8. cache-ref        其他命名空间缓存配置的引用

其中,有一个parameterMap ,已经被放弃使用了。

二. Select 元素的配置

数据库数据为:

在这里插入图片描述
在以前的mapper 映射中:

	<select id="getById"  parameterType="int" resultType="user">
		<!-- 设置别名 -->
		select * from user where id=#{id}
	</select>

select 下面有 id属性,parameterType 参数类型, resultType 结果类型属性等节点, 这些不同的节点表示不同的作用与意义。 除了这些之外,还有其他的节点属性。 只需要记住一些常见的节点即可。

二.一 所属节点

在这里插入图片描述
在这里插入图片描述

下面就开始讲解 select元素的常见使用。

二.二 like 的用法查询记录的数量

在UserMapper.java 接口中:

public int countByName(String name);

在UserMapper.xml 配置中其对应的配置语句为:

<!-- 传入参数查询数目 -->
	<select id="countByName" parameterType="string" resultType="int">
		<!--单个的,可以用value 来接收-->
		select count(*) from user where name like '${value}'
	</select>

测试方法为:

@Test
	public void countByNameTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		int count=userMapper.countByName("%蝴蝶%");
		System.out.println("输出数目为:"+count);
	}

控制台显示为:

在这里插入图片描述

缺点, 上面传入的参数 需要自己手动拼接 %% 连接符, 用户只需要传入参数即可。 真正的拼接,应该放在数据库去完成。 每个数据库都有自己对应的字符串拼接方式。 mysql 可以使用 concat() 函数, oracle 可以使用 || .

<!-- 传入参数查询数目 -->
	<select id="countByName" parameterType="string" resultType="int">
		select count(*) from user where name like concat('%',#{name},'%')
	</select>

上面是两个%%的形式,如果是前% 为 concat(’%’,#{name}), 后%为 concat(#{name},’%’);

三. 传参 parameterType

传参可以使用三种方式

  1. map 方式的传参(较旧的方式)
  2. 注解@Param 的方式 (适用于参数较少的情况,且与实体属性无太太关联)
  3. 实体对象bean 的方式 (适用于插入,更新 等与实体属性关联的,或者属性过多的时候,封装成bean传入)

三.一 Map 形式的传参

接口:

//多个参数的时候。
	public List<User> findByNameAndSexMap(Map<String,Object> map);

xml配置实现

<!-- 查询多个参数的时候 ,map 的形式  parameterType='map' map为系统定义好的别名-->
	<select id="findByNameAndSexMap" parameterType="map" resultType="user">
		select * from user where name like concat('%',#{name},'%') and sex=#{sex} 
	</select>

测试方法:

@Test
	public void findByNameAndSexMapTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		//定义参数
		Map<String,Object> paraMap=new HashMap<String,Object>();
		//key与xml 中配置的相同
		paraMap.put("name","蝴蝶");
		paraMap.put("sex","男");
		List<User> allList=userMapper.findByNameAndSexMap(paraMap);
		allList.forEach(n ->System.out.println(n));
	}

在这里插入图片描述

要注意,map 中的key 键值 要与 sql语句中的#{值} 保持一致。

三.二 @param 注解的方式

接口:

public List<User> findByNameAndSexAnnotation(@Param(value="name") String name,
			@Param(value="sex") String sex);

sql语句配置:

<!-- 查询多个参数的时候 ,注解 的形式, 没有参数类型  -->
	<select id="findByNameAndSexAnnotation" resultType="user">
		select * from user where name like concat('%',#{name},'%') and sex=#{sex} 
	</select>

测试方法, 为传参的形式

@Test
	public void findByNameAndSexAnnotationTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		List<User> allList=userMapper.findByNameAndSexAnnotation("蝴蝶","男");
		allList.forEach(n ->System.out.println(n));
	}

查询的结果与上面的一样。
此时,sql语句中的值要与 注解的value 值相同,不一定要与方法中的形参的值相同。 适用于参数较少的情况,一般不超过5个。

三.三 对象bean 的方式

接口:

	public List<User> findByNameAndSexBean(User user);

sql语句:

<!-- 实体对象bean的方式传参, 已经定义好别名user了 -->
	<select id="findByNameAndSexBean" parameterType="user" resultType="user">
		select * from user where name like concat('%',#{name},'%') and sex=#{sex} 
	</select>

测试方法:

@Test
	public void findByNameAndSexBeanTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		User user=new User();
		user.setName("蝴蝶");
		user.setSex("男");
		List<User> allList=userMapper.findByNameAndSexBean(user);
		allList.forEach(n ->System.out.println(n));
	}

查询的结果与上面的一致。

三.四 三种传参方式的比较

map 形式: map传入进去,是不知道key值是什么的,与sql 语句隔离了,导致了业务可读性的丧失,导致了后续的扩展与维护的困难,应当果断废弃这种方式。

param 注解方式: 受参数个数的影响, 当n<=5 时,是最好的方式, 比java bean 还好,应该比java bean 更直观。 当n>5 时,多个参数调用会出现困难。

java bean 方式: 当参数个数过多时使用。 >5 时。

四. MyBatis 排序

排序,用order by 进行排序。

四.一 单个参数排序,用value 接收

接口:

public List<User> orderByAge(String age);

sql语句:

<!-- 单个值排序,必须用value 进行接收 -->
	<select id="orderByAge" parameterType="string" resultType="user">
		<!-- select * from user order by ${value} desc -->
		select * from user order by ${value} desc
	</select>

测试方法:

	@Test
	public void orderByAgeTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		List<User> allList=userMapper.orderByAge("age");
		allList.forEach(n ->System.out.println(n));
	}

在这里插入图片描述

四.二 多个参数排序 ,用注解方式传入

接口:

public List<User> orderByAgeAndId(@Param("age") String age,@Param("id") String id);

sql语句:

<!-- 多个参数排序,可以用注解的方式 -->
	<select id="orderByAgeAndId"  resultType="user">
		select * from user order by ${age} asc,${id} desc
	</select>

测试方法:

@Test
	public void orderByAgeAndIdTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		List<User> allList=userMapper.orderByAgeAndId("age","id");
		allList.forEach(n ->System.out.println(n));
	}

在这里插入图片描述

五. 查询某些列的值

在sql 语句的前面进行查询

接口:

public List<User> selectColumn(@Param(value="column1") String column1,
			@Param(value="column2") String column2,@Param(value="column3") String column3);

sql语句:

<select id="selectColumn" parameterType="map" resultType="user">
		<!-- 也可以写别名进行操作。 -->
		select ${column1},${column2},${column3} from user
	</select>

测试方法:

@Test
	public void selectColumnTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		List<User> allList=userMapper.selectColumn("name","sex","description");
		allList.forEach(n ->System.out.println(n));
	}

在这里插入图片描述

只有要查询的列才有值。

六. 查询结果 resultType

六.一 最简单的形式查询

数据表的字段要与实体Bean 的类属性保持一致。 如,在实体类中是:
在这里插入图片描述

数据库中是:
在这里插入图片描述

属性与字体一致的,可以进行相应的查询。

接口:

public List<User> findAll();

sql语句:

<select id="findAll" resultType="user">
		select * from user 
	</select>

测试方法:

@Test
	public void findAllTest(){
		SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
		UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
		List<User> allList=userMapper.findAll();
		allList.forEach(n ->System.out.println(n));
	}

在这里插入图片描述

如果数据表的名称与属性不一致的话,那么此时的查询呢? name和age不一致的情况。

在数据表中,将原先的name 改成 u_name, age 改成u_age

在这里插入图片描述

这个时候的查询呢?

在这里插入图片描述
发现 name 和age 是没有值的, 因为无法正确的setter 和getter,所以是取不到值的。

六.二 别名的方式查询,使表字段与类属性相同。

<!-- 使用别名方式查询,令别名为 类属性 -->
	<select id="findAll" resultType="user">
		select id,u_name as name,u_age as age,sex,description from user 
	</select>

这个时候运行查询,是正确的。

在这里插入图片描述
如果现在列名改成了,多个sql 语句查询时,都要设置别名,是不是太麻烦了呢?

六.三 使用resultMap 来实现

将结果集重新定义,定义成 resultMap 便可以了。 resultMap的详细用法,在一对一,一对多的关联关系中会仔细讲解。

<!-- 定义结果类型的 map集合形式 -->
	<resultMap type="user" id="userResultMap">
		<!-- 指定主键用id, column为表列名, property 为类属性 -->
		<id property="id" column="id"/>
		<!-- 普通属性用 result -->
		<result property="name" column="u_name"/>
		<result property="sex" column="sex"/>
		<result property="age" column="_age"/>
		<result property="description" column="description"/>
	</resultMap>
	<!-- 使用resultMap方式查询 -->
	<select id="findAll" resultMap="userResultMap">
		select * from user 
	</select>

查询时,可以正确的查询出来值。

在这里插入图片描述

resultMap 是很强大的元素, 以后会重点讲解。

七. 插入的元素 insert 属性

在这里插入图片描述

关于insert 的用法,可以参看第三章的知识。

其中,插入的时候,可能并不是以1 进行插入,会自定义规则。 测试方法与前面的一样,sql接口是:

<!-- 复杂的插入 -->
	<insert id="insertUser" parameterType="user" useGeneratedKeys="true"
	keyProperty="id">
		<selectKey keyProperty="id" resultType="int" order="BEFORE">
			select if(max(id) is null,1,max(id)+2) as newId from user
		</selectKey>
		insert into user(id,name,sex,age,description) 
		values(#{id},#{name},#{sex},#{age},#{description})
	</insert>

八. 更新的元素 update 和删除的元素 delete

关于update 和delete的用法,可以参看第三章的知识。

九. sql 元素

在一个表中, 用select * from user 中 select * 是不太好的,实际开发中会用属性来代替, 如select id,u_name,sex,u_age,descrption from user 那么这个前面的查询会写很多个,如果改变了其中的一个字段,那么就要改变多个。 可以先将这个select id,u_name,sex,u_age,description 先当成sql 片段定义起来,然后再各个地方进行引用即可。

九.一 普通单个引用

	<sql id="userSql">
		id,u_name,sex,u_age,description
	</sql>
	<select id="findAll" resultMap="userResultMap">
		select <include refid="userSql"/> from user 
	</select>

用sql元素来定义片段, 用 include 来引入片段。

九.二 带参数的复杂引用

	<!-- 用的是$ 拼接符 -->
	<sql id="userSql">
		${prefix}.id,${prefix}.u_name,${prefix}.sex,${prefix}.u_age,${prefix}.description
	</sql>
	<select id="findAll" resultType="user">
		select <include refid="userSql">
					<property name="prefix" value="t"/>
				</include>
		from user t
	</select>

注意,用的是${}, 并不是以前常用的#{} .

谢谢!!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值