SSMday3——掌握SQL映射文件

SQL映射文件

MyBatis真正强大之处就在于SQL映射语句,也是他的魅力所在。相对于它强大的功能,SQL映射文件的配置却非常简单。在之前,我们简单比对了SQL映射配置和JDBC代码,发现用SQL映射文件配置可减少50%以上代码量。并且MyBatis专注于SQL,对于开发人员来说,也可极大限度地进行SQL调优,以保证性能。

SQL映射文件常用的元素配置:

1.mapper:映射文件的根元素节点,只有一个属性namespace(命名空间),其作用:

 (1)、用于区分不同的mapper,全局唯一。

 (2)、绑定DAO接口、即面向接口编程。当namespace绑定某一接口之后,可以不用写该接口的实现类、MyBatis会通过接口的完整限定名
 查找到相对应的mapper配置来执行SQL语句。因此namespace的命名必须要跟接口同名。

2.cache:配置给定命名空间的缓存。

3.cache-ref:从其他命名空间引用缓存配置。

4.resultMap:用来描述数据库结果集和对象的对应关系。

5.sql:可以重用的SQL块,也可以被其他语句引用。

6.insert:映射插入语句。

7.update:映射更新语句。

8.select:映射查询语句。

9.delete:映射删除语句。

查询

与查询对应的select元素是使用MyBatis时最常用的。
1.不带条件的查询

<select resultType="com.bean.User" id="findAll">
select * from user 
</select>
public List<User> findAll();
我们使用findAll()方法,我们的返回值是List<Users>,但是映射文件中还是User类,
这是MyBatis的特性,不关注集合的类型,只关注元素的类型。

2.单条件查询

<select resultType="com.bean.User" id="findById" parameterType="int">
select * from user where id=${id} 
</select>
id:命名空间中唯一标识符,可以被用来引用这条语句。
parameterType:表示查询语句传入参数的类型的完全限定名或者别名。它支持基础数据类型和复杂数据类型。
			   对于普通的java类型,有许多内件的别名并且它们对大小写不敏感。例如:String类型得别名时string,Integer类型得别名integer
			   对自己编写的类命名别名需要在Mybatis配置文件中的typeAliases命名

resultType:查询语句返回结果得完全限定名或别名。别名的使用方式与parameterType相同。

3.多条件查询
1.封装成对象

public interface UserMapper{
/*
查询用户列表(参数:对象入参)
*/
	public List<User> getUserList(User user);
}
                                      完全限定名                    别名
<select id="getUserList" resultType="com.bean.User" paramterType="User">
select * from n_user
where username=#{username} and role_id=#{roleId}
</select>

2.使用Map类型
parameterType支持的复杂数据类型除了JavaBean之外,还有Map类型。

public interface UserMapper{
/*
查询用户列表(参数:Map)
*/
	public List<User> getUserListByMap(Map<String,String>userMap);
}
<select id="getUserListByMap" resultType="com.bean.User" paramterType="Map">
select * from n_user
where username=#{username} and role_id=#{roleId}
</select>

总结:Mybatis传入参数类型可以是Java基础数据类型,但是只适用于一个参数的情况,通过#{参数名}即可获取传入的值。若要多参数入参,则需要复杂数据类型来支持,包括Java实体类,Map,通过#{属性名}或#{Map的key}来获取传入的参数值。

简单结果映射(resultMap的简单映射)

应用场景:MySql数据库中有User(id,nickname,realname,pwd,phone,type)表,和category(id,category_name)表,user表中的type属性与category中的id属性关联。要求:查出User表中的所有属性值,并加上category_name的内容且在类中的属性名为typename。

解决方案:
1)修改实体类,User.java增加typename属性,并修改查询用户列表的SQL语句,对用户表和角色表进行连表查询,使用resultType自动映射。
使用resultType做自动映射时,字段名和实体类的属性名必须一致,若不一致,则需要给字段起别名与属性一致。
<select resultType="com.bean.Users" id="findAll">
select
u.id,
u.email,
u.address,
u.create_time createTime ,  <!--实体类中的属性名是createTime,而数据库中的字段名是create_time-->
r.category_name typename
from n_users u
inner join category r on u.type=r.id
order by id 
</select>
2)通过resultMap映射自定义结果。

首先也需要在User实体类中添加typename属性,及其相应的getter和setter方法。
在UserMapper.xml添加和修改如下内容 :

<resultMap type="User" id="userList">
<result property="id" column="id" />
<result property="email" column="email" />
<result property="address" column="address" />
<result peoperty="createTime" column="create_time" />
<result property="typename" column="category_name" />
</resultMap>
<select resultMap="userList" id="findAll"><!--将resultType换成resultMap,属性值为userList-->
select
u.id,
u.email,
u.address,
u.create_time,  
r.category_name <!--将第一种方法使用的别名去除-->
from n_users u
inner join category r on u.type=r.id
order by id 
</select>

reultMap元素用来描述如何将结果集映射到Java对象上,此处使用resultMap对列表展示所需的必要字段进行自由映射,特别是数据库字段名和实体类属性名不一致的情况下。

resultMap元素的属性值和子节点:
	1.id属性:唯一标识,用于被select的resultMap属性引用
	2.type属性:表示该resultMap的映射结果类型
	3.result子节点:用于标识一些简单的属性,其中column属性表示从数据库中查询的字段名,property则表示查询出来的字段名对应的实体类的属性名。
	4.id子节点:后面论述。

查询返回值类型对比(resultMap与resultType的对比)

Mybatis中对查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap。

区别:

1.resultType
	resultType直接表示返回类型,包括基础数据类型和复杂数据类型。
2.resultMap
	resultMap属性则是对外部resultMap元素所定义的引用,对应外部result Map的id,表示返回结果映射到哪一个resultMap上。
	使用场景一般是:数据库字段信息与属性对象不一致或者需要做复杂的联合查询,以便自由控制映射结果。

关联:

在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。
当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性(调用属性的setter方法)。
所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对
应的值赋给resultType所指定对象的属性;
而当我们提供的返回类型是resultMap的时候,因为Map不能很好表示领域模型,
我们就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。
但两者绝对不能同时存在,只能二者选其一。

resultMap元素的自动映射级别:
当我们选择部分字段进行resultMap映射,我们希望没有映射的字段不能在后台查询并输出,即使SQL语句时查询所有字段 (select * from…)。但是按照上述方法配置resultMap,没有映射的字段一样有数据。
这和resultMap的自动映射级别有关,在Mybatis中,使用resultMap能够进行自动映射的前提时字段名和属性名必须一致,
在默认映射级别(PARTIAL)情况下,若字段名和属性名一致,即使没有做属性名和字段名的匹配,也可以获取未匹配过的属性值,若不一致,则不行。

增加

Mybatis实现增加操作,使用的是insert元素来映射插入语句。
首先在UserMapper接口中增加add()方法

public int add(User user);
//要插入的User对象作为入参,返回值为int类型,即返回执行SQL语句影响的行数。
<insert parameterType="com.bean.Users" id="add">
insert into n_users(nickname,realname,pwd,phone,email,address,create_time,type,realid)
values(#{nickname},#{realname},#{pwd},#{phone},#{email},#{address},#{createTime},#{type},#{realid}) 
</insert>
id:与select元素的id一样,是命名空间中唯一的标识符,可以用来引用该语句。
parameterType:与select元素的parameterType一样,是传入参数的类型的完全限定名或别名。

注意:
对于增删改(insert、delete、update)这类数据库更新操作,需要注意:
1)该类型的操作本身默认返回执行SQL语句影响行数,所以DAO层的接口方法的返回值一般设置为int类型。最好不要返回boolean类型。
2)这三种元素中均没有resultType属性,只有查询操作需要对返回结果类型(resultType/resultMap)进行相应的指定
3)在调用完这三种方法之后,需要commit提交事务,完成数据的更新操作。

修改

Mybatis实现修改操作,使用的是update元素来映射修改语句。具体方法与insert相似。
首先在UserMapper接口中增加update方法。

public int update(User user);
<update parameterType="com.bean.Users" id="update">
update n_users 
set nickname = #{nickname},realname = #{realname},pwd = #{pwd},phone = #{phone},email = #{email},address = #{address},create_time = #{createTime},type = #{type},realid = #{realid}
where id = #{id} 
</update>
update元素的属性id和parameterType的含义和用法等同于insert元素中的属性用法。

多参数入参

如果不用JavaBean和Map类进行多参数入参,即直接进行多参数入参。
解决方法:
@Param注解

User MutiParameter(@Param("id")int id,@Param("username")String username);
<select id="MutiParameter" resultType="com.bean.User">
		select * from user where id = #{id} and username = #{username}
</select>

@Param注解放在接口方法的前面@Param(“内容”)里面的内容和我们sql语句里面#{内容}里面的内容需要一致才能查找到

删除

Mybatis实现删除操作,使用的是update元素来映射删除语句。具体方法与insert、update相似。
首先在UserMapper接口中增加delete方法。

public int delete(int id);
<delete parameterType="int" id="delete">
delete from n_users where id = #{id} 
</delete>
delete元素的属性id和parameterType的含义和用法等同于insert、update元素中的属性用法。

实现高级结果映射

resultMap基本结果配置

	一、属性:
	1.id属性:唯一标识,用于被select的resultMap属性引用
	2.type属性:表示该resultMap的映射结果类型
	二、子节点
	1.result子节点:用于标识一些简单的属性,其中column属性表示从数据库中查询的字段名,property则表示查询出来的字段名对应的实体类的属性名。
	2.id子节点:一般对应数据库中该行的主键id,设置项可以提升Mybatis性能。

高级结果映射

例子:有新闻类(id,title,usersid,context等属性),用户类(id,name等属性)一个新闻只能由一个用户创建,所以新闻到用户时一对一的关系;一个用户可以创建多个新闻,所以用户到新闻时一对多的关系。

1.使用association处理一对一关联关系

修改实体类。

public class News {
    private int id;
    private String title;
    private String content;
    private int usersId;
    private Date pubtime;
    private int state;
    private Date checkTime;
    private int isElite;
    private String keywords;
    //添加User属性
    private User user;
    //设置setter和getter方法
    }

修改NewMapper.xml

<resultMap type="News" id="newsUserResultMap">
    <id property="id" column="id" />
    <result property="title" column="title" />
    <result property="content" column="content" />
    <result property="userId" column="user_id" />
    <result property="pubtime" column="pubtime" />
    <result property="state" column="state" />
    <result property="checkTime" column="checkTime" />
    <result property="isElite" column="isElite" />
    <result property="keywords" column="keywords" />

    <!-- 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>

<!-- 一对一关联,查询订单,订单内部包含用户属性 -->
<select id="queryNewsUserResultMap" resultMap="newsUserResultMap">
    SELECT
    o.id,
    o.title
    o.content
    o.userId,
    o.pubtime,
    o.state,
    o.checkTime,
    o.isElite,
    o.keywords,
    u.username,
    u.address
    FROM
    news o
    LEFT JOIN `user` u ON o.userId = u.id
</select>

测试。

2.使用collection处理一对多管理关系

修改实体类。

public class User{
	private int id;
    private String realname;
    private int type;
    private String realid;
    //添加News属性
    private List<News> news;
    //设置setter和getter方法
}

修改UserMapper.xml

<resultMap type="user" id="userNewsResultMap">
    <id property="id" column="id" />
    <result property="realname" column="realname" />
    <result property="type" column="type" />
    <result property="realid" column="realid" />

    <!-- 配置一对多的关系
        property:填写pojo类中集合类类属性的名称
        ofType:填写集合类型的名称 
    -->
    <collection property="news"  ofType="News">
        <!-- 配置主键,是关联News的唯一标识 -->
        <id property="id" column="id" />
    <result property="title" column="title" />
    <result property="content" column="content" />
    <result property="userId" column="user_id" />
    <result property="pubtime" column="pubtime" />
    <result property="state" column="state" />
    <result property="checkTime" column="checkTime" />
    <result property="isElite" column="isElite" />
    <result property="keywords" column="keywords" />
    </collection>
</resultMap>

<!-- 一对多关联,查询订单同时查询该用户下的订单 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
    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
</select>

测试

补充:

<resultMap type="News" id="newsResultMap">
	<id property="id" column="id" />
    <result property="title" column="title" />
    <result property="content" column="content" />
    <result property="userId" column="user_id" />
    <result property="pubtime" column="pubtime" />
    <result property="state" column="state" />
    <result property="checkTime" column="checkTime" />
    <result property="isElite" column="isElite" />
    <result property="keywords" column="keywords" />
</resultMap>
<resultMap type="user" id="userNewsResultMap">
    <id property="id" column="id" />
    <result property="realname" column="realname" />
    <result property="type" column="type" />
    <result property="realid" column="realid" />
    //使用resultMap重用代码
    <collection property="news"  ofType="News" resultMpa="newsResultMap">
    </collection>
</resultMap>

同理association元素的resultMap用法基本一样的。

配置resultMap自动映射级别

resultMap元素的自动映射级别:
当我们选择部分字段进行resultMap映射,我们希望没有映射的字段不能在后台查询并输出,即使SQL语句时查询所有字段 (select * from…)。但是按照上述方法配置resultMap,没有映射的字段一样有数据。
这和resultMap的自动映射级别有关,在Mybatis中,使用resultMap能够进行自动映射的前提时字段名和属性名必须一致。

  一共三个匹配级别:

1.NONE:禁止自动匹配

2.PARTIAL(默认):自动匹配所有属性, 在默认映射级别情况下,若字段名和属性名一致,即使没有做属性名和字段名的匹配,也可以获取未匹配过的属性值,
若不一致,则不行;有内部嵌套(association、collection)除外。

3.FULL:自动匹配所有属性

我们需要要在mybatis-config.xml中进行配置,默认是PARTIAL

<settings>
	<!--设置resultMap的自动映射级别-->
	<setting name="autoMappingBehavior" value="FULL"/> 
</settings>

Mybatis缓存(了解)

MyBatis存在缓存支持,提供了一级缓存和二级缓存。
1.一级缓存
一级缓存是基于PerpetualCache (Mybatis自带)的 HashMap 本地缓存,作用范围为session域内,当session flush或者close以后,该session中的所有的缓存(cache)会被清空
2.二级缓存
二级缓存就是全局缓存(global caching),超出了session范围之外,可以被sqlSession共享,开启它只需要在MyBatis的核心配置文件(mybatis-config.xml)的setting中设置即可。

一级缓存的是SQL语句,二级缓存的是结果对象

3.二级缓存的配置

二级缓存配置需要在mybatis-config.xml的setting中设置。

<settings>
<seting name="cacheEnabled" value="true" />
</settings>

在mapper文件(如UserMapper.xml)中设置缓存,默认情况下是未开启缓存的。全局缓存的作用域是针对mapper的namespace而言的,只有在这个namespace(com.dao.UserMapper)中查询才能共享cache

<mapper namespace="">
<cache 
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"
 />
</mapper>

在mapper文件配置支持后,如果需要对个别查询进行调整。

<select id="getUserList" resultType="User" useCache="true">
......
</select>

对于的缓存内容仅做了解即可,因为面对一定规模的数据量,内置的Cache方式就派不上用场了;况且对查询结果集做缓存并不是Mybatis框架擅长的,它擅长做的应该是sql映射。所以缓存可以采用(redis等)专门缓存服务器来处理缓存更为合理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值