[转] 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">
1
2
当然,前面不要忘记 xml文件的头部。

<?xml version="1.0" encoding="UTF-8"?>
1
2
一.二 Mapper 根节点
有一个根节点,是mapper, 里面只有一个属性, namespace, 命名空间。 后面跟的值一般为其所在的包路径,或者说是XxxMapper.java 接口所在的包路径。

<mapper namespace="com.yjl.mapper.UserMapper" >
1
一.三 下属节点
在根节点 mapper 下的节点有:

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

二. Select 元素的配置
数据库数据为:

在以前的mapper 映射中:

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

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

二.一 所属节点

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

二.二 like 的用法查询记录的数量
在UserMapper.java 接口中:

public int countByName(String name);
1
在UserMapper.xml 配置中其对应的配置语句为:

<!-- 传入参数查询数目 -->
<select id="countByName" parameterType="string" resultType="int">
<!--单个的,可以用value 来接收-->
select count(*) from user where name like ‘${value}‘
</select>
1
2
3
4
5
测试方法为:

@Test
public void countByNameTest(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
int count=userMapper.countByName("%蝴蝶%");
System.out.println("输出数目为:"+count);
}
1
2
3
4
5
6
7
控制台显示为:

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

<!-- 传入参数查询数目 -->
<select id="countByName" parameterType="string" resultType="int">
select count(*) from user where name like concat(‘%‘,#{name},‘%‘)
</select>
1
2
3
4
上面是两个%%的形式,如果是前% 为 concat(’%’,#{name}), 后%为 concat(#{name},’%’);

三. 传参 parameterType
传参可以使用三种方式

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

//多个参数的时候。
public List<User> findByNameAndSexMap(Map<String,Object> map);
1
2
xml配置实现

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

@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));
}
1
2
3
4
5
6
7
8
9
10
11
12

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

三.二 @param 注解的方式
接口:

public List<User> findByNameAndSexAnnotation(@Param(value="name") String name,
@Param(value="sex") String sex);
1
2
sql语句配置:

<!-- 查询多个参数的时候 ,注解 的形式, 没有参数类型 -->
<select id="findByNameAndSexAnnotation" resultType="user">
select * from user where name like concat(‘%‘,#{name},‘%‘) and sex=#{sex}
</select>
1
2
3
4
测试方法, 为传参的形式

@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));
}
1
2
3
4
5
6
7
查询的结果与上面的一样。
此时,sql语句中的值要与 注解的value 值相同,不一定要与方法中的形参的值相同。 适用于参数较少的情况,一般不超过5个。

三.三 对象bean 的方式
接口:

public List<User> findByNameAndSexBean(User user);
1
sql语句:

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

@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));
}
1
2
3
4
5
6
7
8
9
10
查询的结果与上面的一致。

三.四 三种传参方式的比较
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);
1
sql语句:

<!-- 单个值排序,必须用value 进行接收 -->
<select id="orderByAge" parameterType="string" resultType="user">
<!-- select * from user order by ${value} desc -->
select * from user order by ${value} desc
</select>
1
2
3
4
5
测试方法:

@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));
}
1
2
3
4
5
6
7

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

public List<User> orderByAgeAndId(@Param("age") String age,@Param("id") String id);
1
sql语句:

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

@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));
}
1
2
3
4
5
6
7

五. 查询某些列的值
在sql 语句的前面进行查询

接口:

public List<User> selectColumn(@Param(value="column1") String column1,
@Param(value="column2") String column2,@Param(value="column3") String column3);
1
2
sql语句:

<select id="selectColumn" parameterType="map" resultType="user">
<!-- 也可以写别名进行操作。 -->
select ${column1},${column2},${column3} from user
</select>
1
2
3
4
测试方法:

@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));
}
1
2
3
4
5
6
7

只有要查询的列才有值。

六. 查询结果 resultType
六.一 最简单的形式查询
数据表的字段要与实体Bean 的类属性保持一致。 如,在实体类中是:

数据库中是:

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

接口:

public List<User> findAll();
1
sql语句:

<select id="findAll" resultType="user">
select * from user
</select>
1
2
3
测试方法:

@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));
}
1
2
3
4
5
6
7

如果数据表的名称与属性不一致的话,那么此时的查询呢? 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>
1
2
3
4
这个时候运行查询,是正确的。

如果现在列名改成了,多个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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
查询时,可以正确的查询出来值。

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>
1
2
3
4
5
6
7
8
9
八. 更新的元素 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>
1
2
3
4
5
6
用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>
1
2
3
4
5
6
7
8
9
10
注意,用的是${}, 并不是以前常用的#{} .

谢谢!!!
————————————————
版权声明:本文为CSDN博主「两个蝴蝶飞」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yjltx1234csdn/java/article/details/94588874

原文地址:https://www.cnblogs.com/eedc/p/12628464.html

时间: 2024-09-30 07:22:16

[转] MyBatis的XxxMapper.xml 映射器的详解(六)的相关文章

struts拦截器的详解

1.拦截器:Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. WebWork中文文档解释:拦截器是动态拦截Action调用的对象.它提供了一种机制可以使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个action执行前阻止其执行.同时也提供了一种可以提取Action中可重用的代码的方式. 拦截器栈(Interceptor Stack):Struts2拦截器栈就是将拦截器按

Android开发之AudioManager(音频管理器)详解

AudioManager简介: AudioManager类提供了访问音量和振铃器mode控制.使用Context.getSystemService(Context.AUDIO_SERVICE)来得到这个类的一个实例. 公有方法: Public Methods int abandonAudioFocus(AudioManager.OnAudioFocusChangeListenerl) 放弃音频的焦点. void adjustStreamVolume(int streamType, int dir

花生壳使用及域名映射等问题详解!

提要:如果需要映射域名的话我相信看完我的这篇文章一定会有所帮助的!因为我所遇到的问题都是自己亲身经历的,而且都解决了,相信大家会了解很多事情! 一.使用花生壳原由: 因公司搬家,现在在小区,使用的是联通宽带,不是企业宽带,不能固定ip,懂计算机的人都知道小区宽带,每次上网或是断线重新连接,ip地址都是更改的.至于为什么用小区宽带那无非就是和企业宽带比较起来便宜很多而且网速快点.可是公司有服务器,测试在局域网发布到服务器就可以,但是公司是有网站的,所以小白想了一些办法,前段时间找了家公司,了解了下

springmvc在web.xml中的配置详解

                          <servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-

flowplayer网页视频播放器事例详解--包含各种参数说明(自译)

flowplayer网页视频播放器事例详解--包含各种参数说明(自译) <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">     <title></title>     <meta http-equiv="content-type" content="text/html; charset=UTF-8&

mybatis学习------打包xml映射文件

编译mybatis时,idea不会将mybatis的xml映射文件一起打包进jar,即在编译好的jar包里缺少mybatis映射文件,导致网站加载失败 为解决这个问题,可在mybatis对应module的pom.xml中,找到<build></build>,,在其中添加如下代码即可. <!--将mybatis的xml映射文件一起进行打包--> <resources> <resource> <directory>src/main/jav

Yarn 调度器Scheduler详解

理想情况下,我们应用对Yarn资源的请求应该立刻得到满足,但现实情况资源往往是有限的,特别是在一个很繁忙的集群,一个应用资源的请求经常需要等待一段时间才能的到相应的资源.在Yarn中,负责给应用分配资源的就是Scheduler.其实调度本身就是一个难题,很难找到一个完美的策略可以解决所有的应用场景.为此,Yarn提供了多种调度器和可配置的策略供我们选择. 一.调度器的选择 在Yarn中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,FairS ched

PULL解析XML的运行机制详解

PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL解析器与SAX解析器类似,它提供了类似的事件,例如,开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发事件.每一种事件将作为数值代码被传送,因此使用一个switch来对感兴趣的事件进行处理. 这也是我最喜欢的方法,简单好用. 下面将对解析过程进行详细介绍,它到底是怎么运行

android动画详解六 XML中定义动画

动画View 属性动画系统允许动画View对象并提供很多比view动画系统更高级的功能.view动画系统通过改变绘制方式来变换View对象,view动画是被view的容器所处理的,因为View本身没有要操控的属性.结果就是View被动画了,但View对象本身并没有变化.在Android3.0中,新的属性和相应的getter和setter方法被加入以克服此缺点. 属性动画系统可以通过改变View对象的真实属性来动画Views.而且,View也会在其属性改变时自动调用invalidate()方法来刷