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支持自定义别名
		单个别名的定义
			
				
				
			

		批量定义别名
				
				

4.typeHandlers(类型处理器)

	mybatis中通过typeHandler完成jdbc类型和java类型的转换
	通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义。

5.mappers(映射器)

	单个的映射文件的加载
		
			
	通过mapper接口加载

输出映射:

resultType:

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

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去关联查询用户信息
		
            
            
        
        
        
	上面先执行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中
		
	mapper.xml中
		

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使用二级缓存。