mybatis框架–学习笔记(下)

mybatis框架–学习笔记(下)

上篇: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.address from orders,user where 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:指定查询列中的唯一标识,即订单信息的唯一标识,如果有多个列组成唯一标识,则配置多个id column:查询出来的列名; 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.address from orders,user where 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_id from orders,user,orderdetail where 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_creatime from orders,user,orderdetail,items where 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,需要加上namespace column:表示关联的字段--> <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默认支持一级缓存)

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

mybatis框架--学习笔记(下)

mybatis框架--学习笔记(下)


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

mybatis框架--学习笔记(下)

(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接口的实现类。

mybatis框架--学习笔记(下)

mybatis框架--学习笔记(下)

(3)加入jar包依赖:

mybatis框架--学习笔记(下)

(4)整合ehcache:

mybatis框架--学习笔记(下)

<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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://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 configuration PUBLIC "-//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方法,不需要重新写 @Override public User findUserById(int id) throws Exception{ SqlSession sqlSession=this.getSqlSession();//不需要手动关闭sqlSession System.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:

mybatis框架--学习笔记(下)

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>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114728.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • OpenHarmonyOS for Hi3516dv300[通俗易懂]

    OpenHarmonyOS for Hi3516dv300[通俗易懂]OpenHarmonyOSforHi3516dv300一、安装dockermkdiropenHarmonycdopenHarmonysudosnapinstalldocker#获取docker镜像sudodockerpullswr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1#运行镜像sudodockerrun-it-v$(pwd):/h

  • linux基本命令_Git常用命令

    linux基本命令_Git常用命令用一个记一个。修改文件权限:chmod777文件名文件夹及其子文件:chmod-R777文件夹

  • 两款工控控件对比评测:Iocomp和ProEssentials

    两款工控控件对比评测:Iocomp和ProEssentials对于程序员来说,要凭一己之力开发出漂亮逼真的工控仪表和工控图表是非常耗时间和精力的,那么使用专业的第三方控件就是不错的选择,不仅节约开发时间,降低了项目风险,最重要的是第三方控件写的程序更专业,工控图

  • typescript web_jenkins自动编译

    typescript web_jenkins自动编译前言上一篇我们讲到如何手动编译TypeScript,如果我们每次都要手动编译,那么这样会很累,接下来就介绍自动编译TypeScript。mac自动编译typescript在Typescript文

  • Web后端基础知识[通俗易懂]

    Web后端基础知识[通俗易懂]文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:以下是本篇文章正文内容,下面案例可供参考一、pandas是什么?示例:pandas是基于NumPy的一种工具,该工具是为了解决数据分析任务而创建的。二、使用步骤1.引入库代码如下(示例):importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltimportseabornassnsimportwarnings

  • Svn服务启动的两种方式

    Svn服务启动的两种方式一、svn服务器启动›cmd命令行启动:vsvnserve-d–r文档仓库路径-d后台执行›-r版本库的根目录二、›Windows服务自动启动利用xp、2000以上的系统自带的工具

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号