mybatis学习进阶(5)

二、mybatis进阶     高级映射 查询缓存 和spring整合

1、入门阶段复习

mybatis:一个持久层框架

低成本,高回报。让程序员把精力放在sql语句上,对sql语句优化非常方便,适用于需求变化较多的项目,egg:互联网项目

mybatis框架执行过程:

l  配置mybatis的配置文件,SqlMapConfig.xml

l  通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂

SqlSessionFactory在实际使用时按单例方式进行管理

l  通过SqlSessionFactory创建SqlSession

SqlSession是一个面向用户的接口(提供操作数据库方法),它的实现对象是线程不安全的,建议SqlSession应用场合在方法体内。

l  调用sqlSession的方法去操作数据

如果需要提交事务,需要执行SqlSession的commit()方法

l  释放资源,关闭SqlSession

mybatis开发dao的方法

原始dao的方法:

需要程序员编写dao接口和实现类

需要在dao实现类中注入一个SqlSessionFactory工厂

mapper代理开发方法

只需要程序员编写mapper接口(即dao接口)

程序员在编写mapper.xml(映射文件)和mapper.java需要遵循一个开发规范

规范:mapper.xml中namespace就是mapper.java的类全路径

mapper.xml中statement的id和mapper.java中方法名一致

mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入,参数类型一致

mapper.xml中statement的resultType指定输出结果的类型和mapper.java的方法返回值类型一致

SqlMapConfig.xml配置文件:属性properties、别名typeAliases、映射器mappers..加载

输入映射:

parameterType:指定输入参数类型可以是简单类型,pojo,hashmap

对于综合查询,建议parameterType使用包装的pojo,有利于系统维护,扩展

输出映射:

resultType:

查询到的列名和resultType指定的pojo的属性名一致,才能映射成功

resultMap:

可以通过resultMap完成一些高级映射

如果查询到的列名和映射的pojo的属性名不一致时,通过resultMap设置列名和属性名之间的对应关系(映射关系),可以完成映射

高级映射:

将关联查询的列映射到一个pojo属性中(一对一)

将关联查询的列映射到一个List<pojo>中(一对多)

动态Sql:

if判断

where

foreach

sql片段

2、高级映射:

实现一对一查询、一对多、多对多

延迟加载

2.1、数据模型分析思路

每张表记录的数据内容

分模块对每张表记录的内容进行熟悉,相当于学习系统需求(功能)的过程

每张表重要数据字段设置

非空字段,外键字段

数据库级别表与表之间的关系

外键关系

表与表之间的业务关系

在分析表与表之间的业务关系时一定要建立在某个业务意义基础上分析

数据模型分析

2.2、一对一查询

需求:查询订单信息,关联查询创建订单的用户信息

resultType:

sql语句:

select orders.*,

user.username,user.sex,user.address

from
orders,user where orders.user_id = user.id;

创建pojo:

将上边sql查询的结果映射到pojo中,pojo中必须包括所有查询列名

原始的Orders.java不能映射全部字段,需要新创建的pojo

创建一个pojo继承包括查询字段较多的po类

mapper.xml:

<mapper namespace="com.fzy.mybatis.mapper.OrdersMapperCustom">

<select id="findOrdersUser"
resultType="com.fzy.mybatis.po.OrdersCustom">

select orders.*,

user.username,user.sex,user.address

from orders,user where orders.user_id = user.id;

</select>

</mapper>

mapper.java:

//查询订单关联查询用户信息

public List<OrdersCustom> findOrdersUser() throws Exception;

测试:

public class OrdersMapperCustomTest {

private SqlSessionFactory sqlSessionFactory;

@Before

public void setUp() throws Exception {

String resource = "SqlMapConfig.xml";

InputStream inputStream = Resources.getResourceAsStream(resource);

sqlSessionFactory = new SqlSessionFactoryBuilder()

.build(inputStream);

}

@Test

public void testFindOrdersUser() throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

//创建代理对象

OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);

//调用mapper的方法

List<OrdersCustom> list = ordersMapperCustom.findOrdersUser();

sqlSession.close();

System.out.println(list);

}

resultMap:

sql语句:

select orders.*,

user.username,user.sex,user.address

from
orders,user where orders.user_id = user.id;

使用resultMap映射的思路:

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

需要orders类中添加user属性

//用户信息

private User user;

public User getUser() {

return user;

}

public void setUser(User user) {

this.user = user;

}

mapper.xml:

<!--
订单查询关联用户的resultMap

将整个查询的结果映射到com.fzy.mybatis.po.Orders中

-->

<resultMap type="com.fzy.mybatis.po.Orders"
id="OrdersUserResultMap">

<!-- 配置映射的订单信息 -->

<!-- id:指定查询列中的唯一标识,订单信息中的唯一标识

如果有多个列组成唯一标识,配置多个id

column:订单信息的唯一标识列

properties:订单信息的唯一标识列所映射到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.fzy.mybatis.po.User">

<!-- id:关联查询用户的唯一标识

column:指定唯一标识用户信息的列

javaType:映射到user的哪个属性 -->

<id column="user_id" property="id"/>

<result column="username"
property="username"/>

<result column="sex" property="sex"/>

<result column="address" property="address"/>

</association>

</resultMap>

statement定义:

mapper.java:

//使用resultMap查询订单关联查询用户信息

public List<Orders> findOrdersUserResultMap() throws Exception;

测试:

@Test

public void testFindOrdersUserResultMap() throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

//创建代理对象

OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);

//调用mapper的方法

List<Orders> list = ordersMapperCustom.findOrdersUserResultMap();

sqlSession.close();

System.out.println(list);

}

resultType和resultMap实现一对一查询

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

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

resultMap可以实现延迟加载,resultType不可以实现延迟加载

2.3、一对多查询

需求:

查询订单及订单明细的信息

sql:语句

在一对一查询基础上添加订单明细表关联即可

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;

分析:

要求:

对orders映射不能出现重复记录

在orders.java类中添加List<Orderdetail> orderdetails属性

最终将订单信息映射到orders中,订单所对应的订单明细映射到orders中的orderdetails属性中。(orders信息不重复)

每个orders中的orderdetails属性存储了该订单所对应的订单明细。

在orders.java中添加list订单明细属性

//订单明细

private List<Orderdetail> orderdetails;

mapper.xml:

<!--
查询订单关联查询用户信息及订单明细,使用resultMap -->

<select id="findOrdersAndOrderDetailResultMap"
resultMap="OrdersAndOrderDetailResultMap">

select orders.*,

user.username,user.sex,user.address,

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>

resultMap的定义:

<!--
订单及订单明细的resultMap

使用extends继承,不用在其中配置订单信息和用户信息的映射 -->

<resultMap type="com.fzy.mybatis.po.Orders"
id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">

<!-- 订单信息 -->

<!-- 用户信息 -->

<!-- 使用extends继承,不用在其中配置订单信息和用户信息的映射 -->

<!-- 订单明细信息

一个订单关联查询出了多条明细,要使用collection进行映射

collection:对关联查询到多条记录映射到集合对象中

property:将关联查询到的多条记录映射到com.fzy.mybatis.po.Orders中的哪个属性

ofType:指定映射到list集合属性中pojo的类型

-->

<collection property="orderdetails" ofType="com.fzy.mybatis.po.Orderdetail">

<!-- id:订单明细的唯一标识 -->

<id column="orderdetail_id" property="id"/>

<result column="items_id" property="itemsId"/>

<result column="items_num" property="itemsNum"/>

<result column="orders_id" property="ordersId"/>

<result column="" property=""/>

</collection>

</resultMap>

mapper.java:

//查询订单(关联用户)及订单明细

public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;

单元测试:

小结:

mybatis使用collection对关联查询的多条记录映射到一个List集合属性中

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

 

2.4多对多查询

需求:查询用户及用户购买的商品信息

分析:主表(用户表),关联表(orders,orderdetails,items)

sql语句:

SELECT

orders.*,

USER.username,

USER.sex,

USER.address,

orderdetail.id orderdetail_id,

orderdetail.items_id,

orderdetail.items_num,

orderdetail.orders_id,

items.name items_name,

items.detail items_detail,

items.price items_price

FROM

orders,

USER,

orderdetail,

items

WHERE orders.user_id = user.id AND
orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id

映射思路

将用户信息映射到user中。

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

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

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

mapper.xml

resultMap定义

<!--
查询用户及购买的商品 -->

<resultMap type="cn.itcast.mybatis.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="ordersList"
ofType="cn.itcast.mybatis.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 property="orderdetails"
ofType="cn.itcast.mybatis.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 property="items"
javaType="cn.itcast.mybatis.po.Items">

<id column="items_id" property="id"/>

<result column="items_name" property="name"/>

<result column="items_detail" property="detail"/>

<result column="items_price" property="price"/>

</association>

</collection>

</collection>

</resultMap>

mapper.java

多对多查询总结

将查询用户购买的商品信息明细清单,(用户名、用户地址、购买商品名称、购买商品时间、购买商品数量)

针对上边的需求就使用resultType将查询到的记录映射到一个扩展的pojo中,很简单实现明细清单的功能。

一对多是多对多的特例,如下需求:

查询用户购买的商品信息,用户和商品的关系是多对多关系。

需求1:

查询字段:用户账号、用户名称、用户性别、商品名称、商品价格(最常见)

企业开发中常见明细列表,用户购买商品明细列表,

使用resultType将上边查询列映射到pojo输出。

需求2:

查询字段:用户账号、用户名称、购买商品数量、商品明细(鼠标移上显示明细)

使用resultMap将用户购买的商品明细列表映射到user对象中。

总结:

使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括 多个list。

resultMap总结

resultType:

作用:

将查询结果按照sql列名pojo属性名一致性映射到pojo中。

场合:

常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

resultMap:

使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

association:

作用:

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

场合:

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

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

collection:

作用:

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

场合:

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

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

原文地址:https://www.cnblogs.com/fzywhy/p/9586109.html

时间: 2024-11-08 21:13:52

mybatis学习进阶(5)的相关文章

MyBatis学习总结(五)——实现关联表查询(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(五)--实现关联表查询 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关系. 1 CREATE TABLE teacher( 2 t_id INT PRIMARY KEY AUTO_INCREMENT, 3 t_name VARCHAR(20) 4 ); 5 CREATE TAB

MyBatis学习总结(七)——Mybatis缓存(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(七)--Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空. 2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,Hash

MyBatis:学习笔记(3)——关联查询

MyBatis:学习笔记(3)--关联查询 关联查询 理解联结 SQL最强大的功能之一在于我们可以在数据查询的执行中可以使用联结,来将多个表中的数据作为整体进行筛选. 模拟一个简单的在线商品购物系统,如果我们将用户信息和订单信息都保存在user表中,这样就不存在联结关系,因为我们仅仅操作一张表就好. 但是这是非常不明智的选择,举例来说,一个用户可以拥有多个订单,如果保存在一个表中,势必会导致用户信息的多次出现,因为每个订单绑定的用户信息都是相同的. 所以我们尽量要将不同的信息存储与不同的表中,但

MyBatis学习总结(六)——调用存储过程(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(六)--调用存储过程 一.提出需求 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性 二.准备数据库表和存储过程 1 create table p_user( 2 id int primary key auto_increment, 3 name varchar(10), 4 sex char(2) 5 ); 6 7 insert into p_user(name,sex) values('A',"男");

MyBatis学习总结(八)——Mybatis3.x与Spring4.x整合(转载)

孤傲苍狼 只为成功找方法,不为失败找借口! MyBatis学习总结(八)--Mybatis3.x与Spring4.x整合 一.搭建开发环境 1.1.使用Maven创建Web项目 执行如下命令: mvn archetype:create -DgroupId=me.gacl -DartifactId=spring4-mybatis3 -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false 如下图所示: 创建好的项目如下

mybatis学习笔记(1)

之前做项目的时候,DAO层写了一些spring jdbc,用起来的确不是很方便,今天特意去学习了新的框架:mybatis.把之前用spring-jdbc写的内容换成了mybatis框架搭建的内容. 首先你要到mybatis的官网去下mybatis的jar包:mybatis-3.2.7.jar.由于我是在spring的基础上去搭建mybatis所以还要去弄一个mybatis-spring-1.2.2.jar, 这个连接的包好像在spring官方是找不到的,需要自己去网上找. 进入正题.首先在src

Tomcat 学习进阶历程之Tomcat架构与核心类分析

前面的http及socket两部分内容,主要是为了后面看Tomcat源码而学习的一些网络基础.从这章开始,就开始实际深入到Tomcat的'内在'去看一看. 在分析Tomcat的源码之前,准备先看一下Tomcat的架构与一些核心类的简单分析,并简单介绍一下Tomcat是如何处理一次Http请求的.这部分内容有相当一部分来源于网络,在此,感谢原作者的贡献. Tomcat的总体架构 Tomcat的架构关系可以从Tomcat的配置文件server.xml中看到端倪. 从上图中可以看出Tomcat 的心脏

Mybatis学习笔记(二) 之实现数据库的增删改查

开发环境搭建 mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包.这些软件工具均可以到各自的官方网站上下载.首先建立一个名字为 MyBaits 的 dynamic web project 1. 可以创建maven项目,依赖的包mybatis-3.2.0-SNAPSHOT.jar,mysql-connector-java-5.1.22-bin.jar <!-- mybatis包 --> <depe

【Todo】Mybatis学习-偏理论

之前写过好几篇Mybatis相关的文章: http://www.cnblogs.com/charlesblc/p/5906431.html  <SSM(SpringMVC+Spring+Mybatis)框架程序on IDEA> 还有这个: http://www.cnblogs.com/charlesblc/p/5939505.html   <在上已个Java Spring MVC项目基础上加MyBatis> 还有这篇单独处理Mybatis内容的: http://www.cnblog