[转] MyBatis的XxxMapper.xml 映射器的详解
Posted eedc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[转] 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
以上是关于[转] MyBatis的XxxMapper.xml 映射器的详解的主要内容,如果未能解决你的问题,请参考以下文章