SSM框架学习记录2——Mybatis进阶

mybatis进阶

参考代码:mybatis框架代码及注解进阶

1.SqlMapConfig.xml

properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)

1.properties(属性)
	properties还可以配置一些属性名和属性值
			在properties元素体内定义的属性首先被读取
			然后会读取resource或url中加载的属性,它会覆盖已读取的同名属性
			最后读取parameterType中传递的属性,会覆盖已读取的同名属性
	advice:不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中
	在properties文件中顶一顶属性名一定要有一定的特殊性,如xxxxx.xxx.xxx
2.settings(全局配置参数)
	mybatis框架在运行时可以调整一些运行参数
	如:开启二级缓存,开启延迟加载
	全局参数将会影响mybatis的运行行为
3.typeAliases(类型别名) 重 点
	在mapper.xml中,定义有很多statement,statement需要parameterType指定输入参数类型,需要resultType指定输出结果的映射类型
	如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
	mybatis支持自定义别名
		单个别名的定义
			<typeAliases>
				<!--针对单个别名定义
				type:类型的路径
				alias:别名-->
				<typeAlias type="cn.itcast.mybatis.po.User" alias="user"/>
			</typeAliases>

		批量定义别名
				<!-- 批量别名的定义
				 指定包名,mybatis自动扫描包中的po类,自动定义别名,别名为类名-->
				<package name="cn.itcast.mybatis.po"/>
4.typeHandlers(类型处理器)
	mybatis中通过typeHandler完成jdbc类型和java类型的转换
	通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义。
5.mappers(映射器)
	单个的映射文件的加载
		<!-- 单个的映射文件的加载 -->
			<mapper resource="sqlmap/user.xml"/>
	通过mapper接口加载

输出映射:

resultType:

	使用resultType进行映射,只有查询出的列名和pojo中的属性名一致,才能映射成功
	如果查询出来的列名和pojo中的属性名都不一致,则没创建pojo对象
	如果查询出来的列名和pojo中的属性名有一个一致,就会创建pojo对象
	输出简单类型:
		查询出的结果集只有一行且一列,可以用简单类型进行输出映射。
	输出pojo对象和pojo列表:
		不管输出的pojo是单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定类型是一只的
		在mapper.java指定的方法返回值类型不一样:
			输出单个pojo,返回pojo
			输出掉个pojo,返回list<pojo>

resultMap:

	如果查询出来的列名和pojo中的属性不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系
		select id id_,username username_ FROM user
		1.定义resultMap
		2.使用resultMap作为statement的输出映射
	小结:使用resultType,输出的列名必须与属性名一致
		  如果不一致,则需要使用resultMap

resultType和resultMap的应用:

	用户账号,用户名称,用户性别,商品名称,商品价格
企业开发中常见明细列表,用户购买商品明细列表
使用resultType将上面查询映射到pojo进行输出
	用户账号,用户名称,购买商品数量,商品明细(鼠标上移显示)
使用resultMap将用户购买的商品明细列表映射到user对象中

总结:

使用resultMap是针对那些对查询结果有特殊要求的功能。
resultType和resultMap在一对一,一对多,多对多中的实现与作用:
一对一:
	实现方式:
		resultType:resultType为根据需要而创建出的pojo类型,其中包含所要查询的所有属性。
		resultMap:返回值为resultMap,自定义resultMap
<resultMap id="OrdersUserResultMap" type="mybatis.po.Orders">
	<id column="id" property="id"/>
	<result column="user_id" property="userId"/>
	......
	<association property="user" javaType="mybatis.po.User">
		<id column="user_id" property="id"/>
		<result column="username" property="username"/>
		.......
	</association>
</resultMap>
其中column为唯一标识,property为其在对应类型中的对应属性。
<association> 用于映射关联查询单个对象的信息
一对多实现方式:
resultType:返回的pojo较复杂,不建议使用
resultMap:返回值为resultMap,自定义resultMap
	<resultMap id="OrdersAndOrderDetailResultMap" type="mybatis.po.Orders" extends="OrdersUserResultMap">
		<collection property="orderdetails" ofType="mybatis.po.Orderdetail">
			<id column="orderdetail_id" property="id"/>
			<id column="items_id" property="itemsId"/>
		</collection>
	</resultMap>
	其中extends表示继承其他resultMap,可以简化代码,
	<id>表示唯一标识,同时也表示主键,主键用<id>标签有助于映射
	除去主键的其他属性可以写在<result>标签中,也可使用<id>标签。
多对多实现方式:
resultType:不建议使用
resultMap:返回值为resultMap,自定义resultMap
	<resultMap id="UserAndItemsResultMap" type="mybatis.po.User">
		<id column="user_id" property="id"/>
		<result ......
		<collection property="ordersList" ofType="mybatis.po.Orders">
			<id column="id" property="id"/>
			<result ......
			<collection property="orderdetails" ofType="mybatis.po.Orderdetail">
				<id column="orderdetail_id" property="id"/>
				<result ......
				<association property="items" javaType="mybatis.po.Items">
					<id column="items_id" property="id"/>
					<result ......
				</association>
			</collection>
		</collection>
	</resultMap>
	其中collection用于一对多的映射关系
	association用于一对一的映射关系

6.延迟加载:

resultMap可以实现高级映射,association和collection具备延迟加载的功能。
需求:如果查询订单并且关联用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。
    把对用户信息的按需查询称为延迟加载。
延迟加载:先从单表查询,需要时再从关联表去关联查询,提高数据库性能,因为实现单表要比关联查询多张表速度要快
SELECT
orders.*,
	( SELECT username FROM USER WHERE orders.user_id = USER.id ) username,
	( SELECT sex FROM USER WHERE orders.user_id = USER.id ) sex
FROM
	orders

实现:写两个mapper(sql子查询)

	1.只查询订单信息
	SELECT * FROM orders
	在查询订单的statement中使用association去延迟加载下边的statement(关联查询用户信息)
				
	2.查询用户信息
	通过上面查询到的订单信息中user_id去关联查询用户信息
		<resultMap id="OrdersUserLazyLoading" type="mybatis.po.Orders">
            <id column="id" property="id"/>
            <result ......

            <association property="user" javaType="mybatis.po.User" select="mybatis.mapper.UserMapper.findUserById"
                         column="user_id"/>
        </resultMap>
        <!-- 延迟加载 -->
        <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoading">
            SELECT * FROM orders
        </select>
	上面先执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来

7.SQL标签的使用:

 id:sql片段的唯一标识
 经验:是基于单表来定义sql片段,使sql片段的可重用性更高
 在sql片段中不要包含where

8.查询缓存

作用:如果缓存有数据库就不用访问数据库,提高系统的性能。

	一级缓存:sqlSession级别的缓存
		在操作数据库时需要构造session对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。
		不同的sqlSession之间的缓存数据区域(HashMap)互补影响

	二级缓存:mapper级别的缓存
		多个sqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存。
原理:
一级缓存:mybatis默认开启一级缓存
	<!-- 延迟加载配置 -->
	<settings>
		<!-- 延迟加载开关 -->
		<setting name="lazyLoadingEnabled" value="true"/>
		<!-- 是否积极的加载,设为false不会自动加载,在需要时时候手动加载 -->
		<setting name="aggressiveLazyLoading" value="false"/>
	</settings>
二级缓存:
首先开启mybatis的二级缓存
sqlsession1查询用户1的信息,查询到的用户信息会保存到二级缓存中
sqlsession2查询用户1的信息,会先到二级缓存中查找,再从数据库中查找
与一级缓存的区别,二级缓存的范围更大,多个sqlSession共享一个二级缓存
每一个namespace有一个二级缓存。

1.开启
	需要在sqlMapConfig.xml和mapper.xml中都要开启二级缓存。
	sqlMapConfig.xml中
		<setting name="cacheEnabled" value="true"/>
	mapper.xml中
		<cache/>

2.调用pojo类实现序列化接口
	//实现序列化接口,为了将数据执行反序列化,因为二级缓存数据存储介质多种多样,不一定在内存。
	public class User implements Serializable {

		private int id;
		private String username;
		private int sex;
		private Date birthday;
		private String address;

3.测试
	useCache配置
		即使开启了缓存,调用的数据也不会保存进缓存
		在statement中设置useCache = false 可以禁用语句缓存,即每次查询都会发出sal请求,
		默认情况下是true,即该sql使用二级缓存。
		<select = "findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

				总结:针对每次查询都需要最新的数据的sql,要设置成useCache=false
	刷新缓存flushCache
		在statement这设置 flushCache="true"
		如改成false则不会刷新缓存,使用缓存时,手动修稿数据库的表中的数据会出现脏读

总结:

一般执行完commit操作都需要刷新缓存,flushCache=true 这样可以避免脏读。
刷新间隔flushInterval 一般设置为30,60分钟,24小时,根据需求而定
缓存大小size

应用场景:

	对于访问多的查询请求并且用户对查询结果使用性不高,
	业务场景:如耗时的统计分析sql,电话账单查询sql等。

局限性:

	mybatis 二级缓存对细粒度的数据级别的缓存实现不好,
	(细粒度数据的更改,只更改大量级数据中的极小部分数据)
分布式缓存:(未实现)
不使用分布缓存,缓存的数据在各个服务器单独存储。
不便于系统开发

分布式缓存框架redis,memached,ehcache,
对缓存数据进行集中管理。
如果是单个应用或者对缓存访问要求很高的应用,用ehcache。
如果是大型系统,存在缓存共享、分布式部署、缓存内容很大的,建议用redis。

整合方法
	mybatis提供了一个cache接口,如果实现自己的缓存逻辑,实现cache接口开发即可。
	implement cache


加入ehcache包
	使用ehcache,要添加ehcache包
	ehcache-core.jar
	mybatis-ehcache.jar

整合ehcache
	<cache type="org.mybatis.cache.ehcache.EhcacheCache"/>

在classpath下面添加ehcache的配置文件ehcache.xml
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值