上篇:mybatis框架--学习笔记(上):https://blog.csdn.net/a745233700/article/details/81034021

8、高级映射:

(1)一对一查询:

①使用resultType:

<!-- 一对一查询:resultType -->
<select id="findOrdersUser" resultType="com.zwp.po.OrdersCustom">select orders.*,user.username,user.sex,user.addressfrom orders,userwhere orders.user_id=user.id
</select>
//Orders的扩展类
public class OrdersCustom extends Orders{//添加用属性private String username;private String sex;private String address;//下面省略get和set方法..
}

②使用resultMap:(association)

使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。

public class Orders {private Integer id;private Integer userId;private String number;private Date createtime;private String note;private User user;//在Orders中添加User属性,一对一//下面省略get和set方法
}
 <!-- 一对一查询:resultMap使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息添加到orders对象的user属性中--><resultMap type="com.zwp.po.Orders" id="OrdersUserResultMap"><!-- 配置订单信息的映射 --><!-- id:指定查询列中的唯一标识,即订单信息的唯一标识,如果有多个列组成唯一标识,则配置多个idcolumn:查询出来的列名; property:映射到Orders的哪个属性--><id column="id" property="id" /><result column="user_id" property="userId" /><result column="number" property="number" /><result column="createtime" property="createtime" /><result column="note" property="note" /><!-- 配置映射的关联的用户信息 --><!-- association:用于映射关联查询的单个对象信息property:要将关联查询的用户信息映射到Orders中的哪个属性 --><association property="user" javaType="com.zwp.po.User"><!-- id:关联查询的唯一标识,column:指定唯一标识的用户的列 --><id column="user_id" property="id" /><result column="username" property="username" /><result column="sex" property="sex" /><result column="address" property="address" /></association> </resultMap>  
  <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">select orders.*,user.username,user.sex,user.addressfrom orders,userwhere orders.user_id=user.id</select>

小结:实现一对一查询:

resultyType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求,建议使用resultyType。

resultMap:需要 单独定义resultMap,实现有点麻烦,如果有对查询结果有特殊要求,使用resultMap可以完成将关联查询映射到pojo的属性中。

resultMap可以实现延时加载,resultyType无法实现延时加载。

(2)一对多查询:(collection)

要求:对orders映射不能出现重复记录。

思路:在order.java类中添加List<OrderDetail>orderDetails属性,最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的orderDetails属性中。

public class Orders {private Integer id;private Integer userId;private String number;private Date createtime;private String note;private User user;//用户信息,一对一//订单明细:一对多private List<Orderdetail> orderdetail;//省略get和set方法
}
         <!-- 一对多查询: --><resultMap type="com.zwp.po.Orders" id="OrdersAndOrderdetailResultMap" extends="OrdersUserResultMap"><!-- 订单信息 --><!-- 用户信息 --><!-- extends继承:可以不用再配置订单信息和用户信息的映射 --><!-- 订单明细信息:一个订单关联查询出了多条明细,要使用collection进行映射collection:对关联查询多条映射到集合对象中;property:将关联查询多条映射到pojo的哪个属性中;ofType:指定映射到list集合属性中pojo的类型。--><collection property="orderdetail" ofType="com.zwp.po.Orderdetail"><id column="orderdetail_id" property="id"/><result column="items_id" property="itemsId"/><result column="items_num" property="itemsNum"/><result column="orders_id" property="ordersId"/></collection></resultMap><select id="findOrdersAndOrderdetailResultMap" resultMap="OrdersAndOrderdetailResultMap">select orders.*,user.username,user.sex,user.address,orderdetail.id orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_idfrom orders,user,orderdetailwhere orders.user_id=user.id and orderdetail.orders_id=orders.id</select>

小结:mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。

如果使用resultType实现:将订单明细映射到orders中的ordertails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在ordertails中。

(3)多对多查询:

映射思路:将用户信息映射到user中。

在user类中添加订单列表属性List<Orders>orderslist,将用户创建的订单映射到orderlist;

在Orders中添加订单明细列表属性List<OrderDetail>orderdetails,将订单的明细映射到orderdetails;

在OrderDetail中添加items属性,将订单明细所对应的商品映射到items。

  <!-- 多对多查询 --><resultMap type="com.zwp.po.User" id="UserAndItemsResultMap"><!-- 配置用户信息 --><id column="user_id" property="id"/><result column="username" property="username"/><result column="sex" property="sex"/><result column="address" property="address"/><!-- 配置订单信息:用户对订单:一对多关系:collection --><collection property="orders" ofType="com.zwp.po.Orders"><id column="id" property="id" /><result column="user_id" property="userId" /><result column="number" property="number" /><result column="createtime" property="createtime" /><result column="note" property="note" /><!-- 配置订单详情信息:订单对订单详情:一对多关系:collection --><collection property="orderdetail" ofType="com.zwp.po.Orderdetail"><id column="orderdetail_id" property="id"/><result column="items_id" property="itemsId"/><result column="items_num" property="itemsNum"/><result column="orders_id" property="ordersId"/><!-- 配置商品信息:订单详情对商品:一对一:association --><association property="items" javaType="com.zwp.po.Items"><id column="itemsid" property="id"/><result column="name" property="name"/><result column="price" property="price"/><result column="detail" property="detail"/><result column="items_creatime" property="creatime"/></association></collection></collection></resultMap><select id="findUserAndItemsResultMap" resultMap="UserAndItemsResultMap">select orders.*,user.username,user.sex,user.address,orderdetail.id orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_id,items.id itemsid,items.name,items.price,items.detail,items.creatime items_creatimefrom orders,user,orderdetail,itemswhere orders.user_id=user.id and orderdetail.orders_id=orders.id and items_id=items.id</select>
public class User {private Integer id;private String username;private String birthday;private String sex;private String address;private List<Orders> orders;
}
public class Orders {private Integer id;private Integer userId;private String number;private Date createtime;private String note;private User user;private List<Orderdetail> orderdetail;
}
public class Orderdetail {private Integer id;private Integer ordersId;private Integer itemsId;private Integer itemsNum;private Items items;
}
public class Items {private Integer id;private String name;private Float price;private String pic;private Date creatime;private String detail;
}

(4)总结:

①resultMap:使用association和collection完成一对一和一对多高级映射,用于对结果有特殊的映射要求。

②association:

作用:将关联查询信息映射到一个pojo对象中。

场合:为了方便查询关联信息,可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。

使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。

③collection:

作用:将关联查询信息映射到一个list集合中。

场合:为了方便查询遍历关联信息可以使用collection,将关联信息映射到list集合中,比如:查询用户权限范围模块下及模块下的菜单,可以使用collection将其权限模块映射到权限模块list中,将菜单列表映射到权限模块对象的菜单list属性中,这样做的目的也是方便对查询结果进行遍历查询。

如果使用resultType无法将查询结果映射到List集合中。

9、延时加载:

resultMap的association和collection具备延时加载功能。

延时加载:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多表速度要快。

(1)使用association中的select指定延迟加载去执行的statement的id

 <!-- 延迟加载:查询用户订单信息:用户信息要求延迟加载 --><resultMap type="com.zwp.po.Orders" id="OrderUserLazyLoading"><id column="id" property="id" /><result column="user_id" property="userId" /><result column="number" property="number" /><result column="createtime" property="createtime" /><result column="note" property="note" /><!-- select:表示需要延时加载的statement的id,如果不在同一个namespace,需要加上namespacecolumn:表示关联的字段--><association property="user" javaType="com.zwp.po.User" select="findUserById" column="user_id"><id column="user_id" property="id" /><result column="username" property="username" /><result column="sex" property="sex" /><result column="address" property="address" /><result column="birthday" property="birthday" /></association></resultMap>  <!-- 不可以使用resultType,因为resultType没有延迟加载功能 --><select id="findOrderUserLazyLoading" resultMap="OrderUserLazyLoading">select * from orders</select><!-- 查询订单关联查询用户,用户信息需要延时加载 --><select id="findUserById" parameterType="int" resultType="com.zwp.po.User">SELECT * FROM USER WHERE id=#{id}</select>

(2)延迟加载配置:

Mybatis默认没有开启延时加载,需要在SqlMapperConfig.xml中的setting配置。

 <!-- settings:配置全局变量 --><settings><!-- 开启延迟加载开关 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载,即按需加载 --><setting name="aggressiveLazyLoading" value="false"/></settings>

(3)总结:

使用延时加载方法,先去查询简单的sql(最好是单表,也可以关联查询),再去按需要加载关联查询的其他信息。

10、一级缓存:(mybatis默认支持一级缓存)

缓存:提高系统的性能,减少数据库的压力。

11、二级缓存:(默认不开启)

(1)开启二级缓存:

①在核心配置文件SqlMapConfig.xml中加入:

 <!-- settings:配置全局变量 --><settings><!-- 开启二级缓存 --><setting name="cacheEnabled" value="true"/></settings>

②在xxxMapper.xml文件中开启二级缓存,xxxMapper.xml下的sql执行完会存储到他的缓存区域(HashMap)

<mapper namespace="com.zwp.mapper.OrdersMapperCustom"><!-- 开启本mapper下的二级缓存<cache/>
</mapper> 

(2)useCache配置:禁用二级缓存:

在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认是true,即改sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

场景:针对每次查询都需要更新的数据sql,要设置成useCache=false,禁用二级缓存。

(3)刷新缓存(清空缓存):

设置statement配置中的flushCache="true"属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。

<insert id="insertUser" parameterType="com.zwp.domain.User" flushCache="true">

场景:一般情况下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。

12、分布缓存:mybatis整合ehcache:

分布缓存:可以实现对缓存数据进行集中管理。

(1)Mybatis无法实现分布式缓存,需要和其他分布式缓存框架进行整合。

(2)整合方法:

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

mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个Cache接口的实现类。

(3)加入jar包依赖:

(4)整合ehcache:

<mapper namespace="com.zwp.mapper.OrdersMapperCustom"><!-- 开启本mapper下的二级缓存type:指定cache接口的实现的类型,mybatis默认使用PerpetualCache--><cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

(5)加入ehcache的配置文件:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="D:\develop\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache> 

13、mybatis和spring整合开发:

需要spring通过单例方式管理SqlSessionFactory。

spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSession,持久层的mapper都需要由spring进行管理。

步骤:

(1)导入jar包依赖:

(2)sqlSessionFactory配置:

在applicationContext.xml配置sqlSessionFatory,sqlSessionFatory在mybatis和spring的整合包下。

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 1.加载数据库配置文件 --><context:property-placeholder location="classpath:db.properties"/><!-- 2.配置连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"><property name="driverClass" value="${jdbc.driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.username}"></property><property name="password" value="${jdbc.password}"></property></bean><!-- 3.创建会话工厂sqlSessionFactory -->      <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 加载mybatis的配置文件 --><property name="configLocation" value="mybatis/SqlMapConfig.xml"></property><!-- 配置数据源 --><property name="dataSource" ref="dataSource"></property></bean>
</beans>

(3)①原始dao开发:

--User.xml文件:

<mapper namespace="test"><select id="findUserById" parameterType="int" resultType="com.zwp.ssm.po.User">SELECT * FROM USER WHERE id=#{id}</select>
</mapper>

在SqlMapConfig.xml文件中加载映射文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- 加载映射文件 --><mappers><!-- 通过resource加载单个映射文件 --><mapper resource="sqlmap/User.xml"></mapper></mappers>
</configuration>

--Dao:(实现类继承SqlSessionDaoSupport

public interface UserDao {//根据id查询用户public User findUserById(int id) throws Exception;
}

DaoImpl接口实现类需要注入sqlSessionFactory,通过spring进行注入:

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{//继承SqlSessionDaoSupport//父类已经定义SqlSessionFactory对象和set方法,不需要重新写@Overridepublic User findUserById(int id) throws Exception{SqlSession sqlSession=this.getSqlSession();//不需要手动关闭sqlSessionSystem.out.println(sqlSession);User user=sqlSession.selectOne("test.findUserById",id);return user;}
}

通过spring创建接口的bean对象:

 <!--原始dao接口 --><bean id="userDao" class="com.zwp.Dao.UserDaoImpl"><!-- sqlSessionFactory不能写错 --><property name="sqlSessionFactory" ref="sqlSessionFactory"></property></bean>

(3)②mapper代理开发:

--mapper.xml和mapper.java:

public interface UserMapper {/*(1)mapper.java接口中方法名和mapper.xml中的statement的id一致(2)mapper.java接口中方法的输入参数类型和mapper.xml中statement的parameterType指定的类型一致(3)mapper.java接口中方法的返回值类型和mapper.xml中statement的resultment中resultType指定类型一致。*///根据id查询用户public User findUserById(int id) throws IOException;
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.zwp.ssm.mapper.UserMapper"><select id="findUserById" parameterType="int" resultType="com.zwp.ssm.po.User">SELECT * FROM USER WHERE id=#{id}</select>
</mapper>

----通过mapperFactoryBean创建代理对象(此方法存在问题):

<!-- mapper接口 --><!-- MapperFactoryBean:根据mapper接口生成代理对象 --><bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"><!-- mapperInterface指定mapper接口 --><property name="mapperInterface" value="com.zwp.ssm.mapper.UserMapper"></property><property name="sqlSessionFactory" ref="sqlSessionFactory"></property></bean>

此方法的问题:如果有很多个mapper,需要针对每个mapper进行单独配置。

解决方法:通过MapperScannerConfigure进行mapper批量扫描。

 <!-- mapper批量扫描,从mapper包中扫描出mapper,自动创建代理对象并且在spring容器中注册遵循规范:需要mapper接口类名和mapper.xml映射文件名称一致,且在同一目录下 自动扫描出来的mapper的bean的id为类名(首字母小写)--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!-- 指定扫描的包名 --><!-- 如果扫描多个包,每个包中间使用半角逗号隔开 --><property name="basePackage" value="com.zwp.ssm.mapper"></property><!-- sqlSessionFactoryBeanName不能写成sqlSessionFactory,不然会导致连接不上数据库 --><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean>

mybatis框架--学习笔记(下)相关推荐

  1. mybatis框架--学习笔记(上)

    使用JDBC操作数据库的问题总结: (1)数据库连接,使用时创建,不使用时立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能. 设想:使用数据库连接池管理数据库连接. (2) ...

  2. [Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP

    上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(三):Spring实现JDBC 下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(五):SpringA ...

  3. 2021年3月8日:MyBatis框架学习笔记02:利用MyBatis实现CRUD操作

    MyBatis框架学习笔记02:利用MyBatis实现CRUD操作 在第一节课中我们在UserMapper.xml里定义了两个查询语句:findById和findAll,对应的在UserMapper接 ...

  4. MyBatis框架学习笔记(3)——B站动力节点

    文章目录 (0)介绍 (1)返回主键的标签 (2)UUID的概念 (3)update时< set >标签的使用 (4)表与表的关联关系 一对多关联 多对一关联 一对一关联 多对多关联 (5 ...

  5. MyBatis框架学习笔记(1)——B站动力节点

    文章目录 001- 框架概述 1.1 软件开发常用结构 1.2 框架是什么 1.3 回顾JDBC编程 1.4 MyBatis框架概述 002- MyBatis框架快速入门 2.1 入门案例 2.2 M ...

  6. MyBatis框架学习笔记02:使用MyBatis实现CRUD操作

    文章目录 Ⅰ.查询表记录 (Ⅰ).在映射器配置文件里引入结果映射元素 (Ⅱ).添加按姓名查询用户记录功能 1).在UserMapper.xml里添加映射语句 - findByName 2).在User ...

  7. MyBatis框架学习笔记01:初生牛犊

    文章目录 1. 什么是MyBatis 创建数据库 演示MyBatis基本使用 1.创建Maven项目 创建实体类 创建用户实体类关系映射配置文件 创建测试类 完成测试 1. 什么是MyBatis My ...

  8. MyBatis框架学习笔记04:利用MyBatis实现条件查询

    文章目录 一.查询需求 二.打开MyBatisDemo项目 三.对学生表实现条件查询 (一)创建学生映射器配置文件 (二)在MyBatis配置文件里注册学生映射器配置文件 (三)创建学生映射器接口 ( ...

  9. MyBatis框架学习笔记03:利用MyBatis实现关联查询

    文章目录 一.查询需求 (一)针对三张表关联查询 (二)按班级编号查询班级信息 (三)查询全部班级信息 二.创建数据库表 (一)创建教师表 (二)创建班级表 (三)创建学生表 三.创建与数据库表对应的 ...

最新文章

  1. 34岁,外企倒闭成功上岸大厂,50K,附面试秘籍
  2. 【引用】Android程序实现完全退出
  3. linux中sh基本语法
  4. 036、Linux下ipmitool命令
  5. java分层命名_JAVA基础篇(5)-POJO的命名规则
  6. 【渝粤题库】广东开放大学 会展英语 形成性考核
  7. Git(7)-Git commit
  8. 程序员你真的理解final关键字吗?
  9. Mysql学习总结(50)——Oracle,mysql和SQL Server的区别
  10. albert使用的中文语料
  11. 2957: 楼房重建
  12. 大厂用的分库分表方案和demo源码,都在这里了!
  13. base64原理与实现
  14. mysql删除命令历史记录_MySQL历史命令记录清除
  15. OpenJudge 1.6.4
  16. BIP63(隐身地址)
  17. jquery UI 跟随学习笔记——拖拽(Draggable)
  18. csv文件用excel打开乱码问题
  19. MSBUILD : error MSB4132: The tools version “2.0“ is unrecognized. Available tools versions are “4.0“
  20. 两种红外对管的区别——基于硬件中断(外部中断)测距避障

热门文章

  1. 四十一、深入Java中的 File类
  2. Django的APP,视图,url和模板
  3. Python与常见加密方式
  4. 吊打一切现有开源OCR项目!90% +准确率,训练部署一条龙
  5. 【Java报错】GP数据库 function point(unknown) is not unique.Could not choose a best candidate function 问题解决
  6. 2017计算机考研统考大纲,2017年考研计算机大纲详解(六):计算机网络
  7. findfirstfile函数为什么不能遍历doc_编程之美:IO多路复用——记性不好的poll函数...
  8. Spring Boot-@ImportResource注解
  9. 《计算机网络》实验报告——常用网络命令
  10. Build Tree