Mybatis学习第二天

学习内容:

  1. mybatis的CRUD操作
  2. mybatis的关系映射

Mybatis的CRUD操作

再mybatis中,CRUD变的非常简单,我们可以通过Mapper代理模式来进行CRUD操作,我们甚至可以省略书写CRUD的过程,只用关注于SQL语句

这里只举一个查询所有操作的例子:

1.映射文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.Dao.IUserDao"><!--查找所有的用户--><select id="findAll" resultType="User">SELECT * FROM user</select></mapper>

2.实体类:

import java.io.Serializable;
import java.util.Date;public class User implements Serializable {private  Integer id;private  String username;private  Date birthday;private  String sex;private  String address;@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", birthday=" + birthday +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}

3.Dao层接口


public interface IUserDao {List<User> findAll();}

4.测试代码:

public class Mybatis01 {//4.创建代理对象IUserDao dao;SqlSession sqlSession;@Beforepublic void setup() throws IOException {//1.加载配置文件InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建sqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);//3.生产sqlSession对象sqlSession = sqlSessionFactory.openSession();dao = sqlSession.getMapper(IUserDao.class);in.close();}@Testpublic void test() {List<User> users = dao.findAll();for (User user : users) {System.out.println(user);}}@Afterpublic void close() {sqlSession.close();}}

执行结果如下:


2019-10-09 09:24:47,384 549    [           main] DEBUG com.offcn.Dao.IUserDao.findAll  - ==>  Preparing: SELECT * FROM user
2019-10-09 09:24:47,414 579    [           main] DEBUG com.offcn.Dao.IUserDao.findAll  - ==> Parameters:
2019-10-09 09:24:47,464 629    [           main] DEBUG com.offcn.Dao.IUserDao.findAll  - <==      Total: 6
User{id=1, username='阿水', birthday=Tue May 02 00:00:00 CST 2017, sex='女', address='山西太原'}
User{id=5, username='李晓雨', birthday=Thu Dec 13 00:00:00 CST 2018, sex='男', address='山西大同'}
User{id=6, username='ningque', birthday=Sun Sep 09 00:00:00 CDT 1990, sex='1', address='shanxi'}
User{id=16, username='阿辉', birthday=Thu Sep 13 00:00:00 CDT 1990, sex='女', address='露露安'}
User{id=17, username='zgf35310', birthday=Sun Sep 09 00:00:00 CDT 1990, sex='0', address='事实上'}
User{id=19, username='zgf35310', birthday=Sun Sep 09 00:00:00 CDT 1990, sex='1', address='事实上'}
2019-10-09 09:24:47,465 630    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3aeaafa6]
2019-10-09 09:24:47,466 631    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3aeaafa6]
2019-10-09 09:24:47,466 631    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 988458918 to pool.

Mybatis的关系映射

在我们日常处理的数据的时候,经常会有两或两个以上的表进行协同操作,所以这里就要用到mybatis的关系映射。
关系映射分为 1对1,1对多,多对多。

1对1的关系:

例如下图的两张表:

1.用户信息表

2.身份证信息表

这两张表之间存在1对1的关系,一个用户对应一个身份证号,用户表中的用户id和身份证信息表中的per_fk对应。

我们想在查询用户信息的时候同时查询到身份证号,我们就可以书写sql语句:

SELECT user.*,card.num from user,card where user.id = card.per_fk;

查询结果如图:


我们在这次的查询中,查询的结果即包含用户表中的全部信息,也包含身份证信息表中的部分信息,那我们该如何存储这些信息到实体类中呢?

首先我们想到的就是在User类中,增加一条属性为int num的属性,这样就可以把身份证号存储到用户表中,这个操作固然可行,可是这样我们就不是对应了表之间的关系,而是单纯的按照取出的数据的列来进行封装实体类。
为了解决这个问题,我们可以通过手动映射,建立出互相包含的实体,将表于表之间的关系转换为实体与实体之间的关系。

所以,我们先创建出身份证表的实体类:

public class Card {private  Integer id;private  String name;private  String num;private  long perFk;@Overridepublic String toString() {return "Card{" +"id=" + id +", name='" + name + '\'' +", num='" + num + '\'' +", perFk=" + perFk +'}';}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNum() {return num;}public void setNum(String num) {this.num = num;}public long getPerFk() {return perFk;}public void setPerFk(long perFk) {this.perFk = perFk;}
}

并且在User实体类中添加一条Card类型的属性:

 private Card card;//同时添加get,set方法public Card getCard() {return card;}public void setCard(Card card) {this.card = card;}

接下来就是书写我们的映射文件,来处理如何把查询到的num列的属性存储到User实体类的Card属性中

手动映射的第一种形式:

 <!--一对一的关系映射--><resultMap id="UserAndCard" type="user"><id property="id" column="id" /><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address"/><association property="card" javaType="card"><result property="num" column="num"/></association></resultMap><select id="findOneToOne1" resultMap="UserAndCard">SELECT user.*,card.num from user,card where user.id = card.per_fk;</select>

association标签的作用:

说白了我们只关注两个点
1.property:指的就是你实体类中的存储相关数据的属性名
2.javaType:存储到哪个实体类中

手动映射的第二种形式:

 <resultMap id="findNum" type="card"><result property="num" column="num"/></resultMap><resultMap id="findUserAndCard" type="user"><id property="id" column="id" /><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address"/></resultMap><resultMap id="UserAndCard2" type="user" extends="findUserAndCard"><association property="card" javaType="card" resultMap="findNum"/></resultMap><select id="findOneToOne2" resultMap="UserAndCard2">SELECT user.*,card.num from user,card where user.id = card.per_fk;</select>

和第一种没有太大的区别,只不过是把association中的内容单独拎出去了,封装成了一个resultMap,然后再association标签中再次调用。

手动映射的第三种形式:

这种形式就很麻烦了,也叫做分步查询的形式,并且这种的查询方式的结果和前两种都不同,先查询出所有的用户的信息,封装成一个list集合,再根据所有用户的id查询身份证表,把查到的信息和用户表一一对应,如果查不到就是空值了。

根据上述思路,我们来书写一下:

首先查询所有的用户信息:

 <resultMap id="UserAndCard3" type="user"><id property="id" column="id" /><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address"/></resultMap><select id="findOneToOne3" resultMap="UserAndCard3">SELECT * FROM user</select>

查询到了所有的用户信息之后就要查询所有用户的身份证信息,存储到用户信息中

 <association property="card" javaType="card" column="id" select="com.offcn.Dao.IUserDao.getUserByCard"/><select id="getUserByCard" parameterType="int" resultType="card">select * from card where per_fk=#{uid}</select>

最后组合在一起

<resultMap id="UserAndCard3" type="user"><!--映射完毕后开始查询Card中的信息,再次封装到User中--><id property="id" column="id" /><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address"/><association property="card" javaType="card" column="id" select="com.offcn.Dao.IUserDao.getUserByCard"/></resultMap><select id="findOneToOne3" resultMap="UserAndCard3">SELECT * FROM user</select><select id="getUserByCard" parameterType="int" resultType="card">select * from card where per_fk=#{uid}</select>

注意: association 中 property代表数据赋值给实体类中的属性名称,column代表将何值传递给下一条sql语句作为参数进行查找。

查询结果:

-------------这是一个From findOneToOne3-------------
User{id=1, username='阿水', birthday=Tue May 02 00:00:00 CST 2017, sex='女', address='山西太原'}
Card{id=1, name='ddd', num='140622100987636343', perFk=0}
-------------这是一个From findOneToOne3-------------
User{id=5, username='李晓雨', birthday=Thu Dec 13 00:00:00 CST 2018, sex='男', address='山西大同'}
Card{id=2, name='fff', num='109876543211234567', perFk=0}
-------------这是一个From findOneToOne3-------------
User{id=6, username='ningque', birthday=Sun Sep 09 00:00:00 CDT 1990, sex='1', address='shanxi'}
null
-------------这是一个From findOneToOne3-------------
User{id=16, username='阿辉', birthday=Thu Sep 13 00:00:00 CDT 1990, sex='女', address='露露安'}
null
-------------这是一个From findOneToOne3-------------
User{id=17, username='zgf35310', birthday=Sun Sep 09 00:00:00 CDT 1990, sex='0', address='事实上'}
null
-------------这是一个From findOneToOne3-------------
User{id=19, username='zgf35310', birthday=Sun Sep 09 00:00:00 CDT 1990, sex='1', address='事实上'}
null
2019-10-09 20:25:06,481 756    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@462d5aee]
2019-10-09 20:25:06,482 757    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@462d5aee]
2019-10-09 20:25:06,482 757    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1177377518 to pool.

前两个查询的结果:

-------------这是一个From findOneToOne2-------------
User{id=1, username='阿水', birthday=Tue May 02 00:00:00 CST 2017, sex='女', address='山西太原'}
Card{id=null, name='null', num='140622100987636343', perFk=0}
-------------这是一个From findOneToOne2-------------
User{id=5, username='李晓雨', birthday=Thu Dec 13 00:00:00 CST 2018, sex='男', address='山西大同'}
Card{id=null, name='null', num='109876543211234567', perFk=0}
2019-10-09 20:29:55,779 741    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@462d5aee]
2019-10-09 20:29:55,780 742    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@462d5aee]
2019-10-09 20:29:55,780 742    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1177377518 to pool.

我们可以明显的发现,前两种和sql语句的查询结果相同,只把匹配的上的信息查询出来了,而第三种则是把所有的信息都查询出了,没有身份证信息的则为null。

一对多

一对多和一对一其实道理相同,只不过是把一条用户信息的id所能查询到的所有的订单信息都封装为多个实体类,并且把这个实体类存储在List集合中,在映射文件中使用Collection标签来处理。

先上表:

订单表

用户表

一对多同样有三种形式

第一种

 <resultMap id="UserAndOrder1" type="user" extends="findUserAndCard"><collection property="orders"  ofType="order"><result property="userId" column="userId"/><result property="number" column="number"/><result property="note" column="note"/><result property="createTime" column="createTime"/></collection></resultMap><select id="findOneToMany1" resultMap="UserAndOrder1">SELECT u.*,o.* FROM user u,orders o WHERE u.id = o.userId;/*select u.*,o.number,o.note from user u,orders o where u.id=o.userId*/</select>

第二种

 <resultMap id="findOrders" type="order"><result property="userId" column="userId"/><result property="number" column="number"/><result property="note" column="note"/><result property="createTime" column="createTime"/></resultMap><resultMap id="UserAndOrder2" type="user" extends="findUserAndCard">as<collection property="orders"  ofType="order" resultMap="findOrders"/></resultMap><select id="findOneToMany2" resultMap="UserAndOrder2">SELECT u.*,o.* FROM user u,orders o WHERE u.id = o.userId;</select>

第三种

 <resultMap id="UserAndOrder3" type="user" extends="findUserAndCard"><collection property="orders" ofType="order" column="id" select="com.offcn.Dao.IUserDao.findOrdersById"/></resultMap><select id="findOneToMany3" resultMap="UserAndOrder3">SELECT * FROM USER</select><select id="findOrdersById" resultType="order" parameterType="int">SELECT * FROM ORDERS WHERE USERID = #{UID}</select>

执行结果就省略了,其实一对多和一对一非常相似,仅仅是将association 标签替换为 collection标签,标签中将javaType改为ofType。

多对多

多对多其实和一对多也类似,只不过多对多要添加一张中间表,中间表联系两张表的多对多关系,废话少说,上表

items表

orders表

orderdetail中间表

通过这三张表我们可以看出:

所以我们现在关键的是要把这三张表联合起来,查询出结果我们可以通过左外连接书写的sql语句来把三张表联系在一起

select o.id as oid, o.note,i.* from orders o
left outer join orderdetail od on o.id = od.ordersId
left outer join items i on od.itemsId = i.id;

测试查询结果如图:


既然可以查询出结果,也就是说这两张表联系在了一起,那么我们就可以在实体类中添加两方的关系,两方既然是多对多的关系,那么就可以在Order实体类中添加一个泛型为Item的集合,在Item的实体类中,添加一个泛型为Order的集合。

//Order实体类中添加:
private List<Item> items;public List<Item> getItems() {return items;}public void setItems(List<Item> items) {this.items = items;}
//List实体类中添加:
private List<Order> orders;public List<Order> getOrders() {return orders;}public void setOrders(List<Order> orders) {this.orders = orders;}

实体类配置完毕,映射文件的思路就很简单了,把表中的映射完毕后,再使用Collection标签把其他表中的映射到集合中就好了

<resultMap id="ItemOrder" type="item"><id property="id" column="id"/><result property="name" column="name"/><result property="price" column="price"/><result property="pic" column="pic"/><result property="createtime" column="createtime"/><result property="detail" column="detail"/><collection property="orders" ofType="order"><id property="id" column="oid"/><result property="note" column="note"/></collection></resultMap><select id="Many2Many2" resultMap="ItemOrder">select i.*,o.id as oid, o.note as note from orders oleft outer join orderdetail od on o.id = od.ordersIdleft outer join items i on od.itemsId = i.id;</select><resultMap id="OrderItem" type="order"><id column="oid" property="id"/><result column="userId" property="userId"/><result column="number" property="number"/><result column="note" property="note"/><result column="createTime" property="createTime"/><collection property="items" ofType="item"><result column="name" property="name"/><result column="price" property="price"/><result column="pic" property="pic"/><result column="createtime" property="createtime"/><result column="detail" property="detail"/></collection></resultMap><select id="ManyToMany" resultMap="OrderItem">select i.*,o.id as oid, o.note as note from orders oleft outer join orderdetail od on o.id = od.ordersIdleft outer join items i on od.itemsId = i.id;</select>

执行结果:
Order–Item

Item–Order

结果没问题,这些就是mybatis的关系映射中的三种关系。喜欢请点赞谢谢!

Mybatis CRUD操作和多表查询相关推荐

  1. mybatis CRUD操作

    mybatis CRUD操作 select select标签是mybatis最常用的标签之一. select语句有很多属性可以详细的配置每一天sql语句. id 命名空间唯一的标识. 接口中的方法名与 ...

  2. MySQL学习笔记03【数据库表的CRUD操作、数据库表中记录的基本操作、客户端图形化界面工具SQLyog】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  3. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  4. mysql第四篇:数据操作之多表查询

    mysql第四篇:数据操作之多表查询 一.多表联合查询 #创建部门 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment P ...

  5. cmd操作MySQL 多表查询(日记 day 4)

    cmd操作MySQL 多表查询 今天记录一下学习多表查询的一些操作,也算是练习记录了. 通过练习排错,来避免知识的盲区和解决心中的一些疑惑 其中的数据.题目是参照b站大刘老师的,我觉得讲的很精炼 有兴 ...

  6. 在thinkphp框架中如何对多表进行操作(thinkphp多表查询方法)

    在thinkphp框架中如何对多表进行操作(thinkphp多表查询方法) 本文讲解了在thinkphp框架中如何对多表进行操作,ThinkPHP是一个开源的PHP框架,是为了简化企业级应用开发和敏捷 ...

  7. week7 day3 记录相关操作之单表查询

    week7 day3 记录相关操作之单表查询 1.1 单表查询的用法 1.2 关键字的执行优先级(重点) 1.3 简单查询 1.4 WHERE约束 1.5 分组查询GROUP BY 1.6 HAVIN ...

  8. Mybatis入门:4(多表查询操作)

    多表查询操作 Mybatis的多表操作 表之间的关系有几种:一对多.一对一.多对一.多对多 举例: 用户和订单就是一对多--一个用户可以下多个订单 订单和用户就是多对一--多个订单属于同一个用户 人和 ...

  9. 用于MyBatis CRUD操作的Spring MVC 3控制器

    到目前为止,我们已经为域类" User "创建了CRUD数据库服务,并且还将MyBatis配置与Spring Configuration文件集成在一起. 接下来,我们将使用Spri ...

  10. MyBatis Plus 如何实现连表查询 mybatis plus join

    mybatis-plus-join 项目地址 gitee github 使用方法 安装 Maven <dependency><groupId>com.github.yulich ...

最新文章

  1. 学习python(五)
  2. AI 机器人也能成佛?日本人觉得可以。
  3. rocketmq还要eventbus_ListEventBuses_ListEventBuses_事件总线_C# SDK_阿里云SDK参考_事件总线EventBridge - 阿里云...
  4. HttpServletRequest中getAttribute()和getParameter()的区别
  5. CI Weekly #11 | 微服务场景下的自动化测试与持续部署
  6. VSCode 开发Vue必备插件
  7. ue4 网络代码分析
  8. Confirm Hosts Registration with the server failed
  9. Java语言程序设计(一)选择题
  10. 使用include实现布局(layout)复用
  11. IT30: 数字化转型之路
  12. 光衰高怎么办_灯太亮了怎么办 led灯该如何选择
  13. mysql 赋权_《MySQL数据库》MySQL用户赋权
  14. 邓俊辉 《数据结构》笔记1 绪论
  15. Android使用WebView无法显示网页
  16. Revit模型在Web端展示的免费方案
  17. 跨次元!目标检测类别超20000!
  18. 为了证明苹果电脑会不会中毒,我把病毒拷了进去
  19. 2019-01-25T01:30:00.000+0000 格式转换
  20. e级超级计算机济南,国之重器!神威E级原型机8月将在国家超级计算济南中心落地...

热门文章

  1. 使用calibration_toolkit进行相机和三维激光雷达的联合标定(详细步骤)
  2. 分布式id黑科技完善
  3. 微信公众号迁移、公证办理流程
  4. Python for s60[1_pys60简介]
  5. python监控服务器cpu温度实例_用python访问CPU温度
  6. 【Steam VR 2.0】自定义按键 action 发布后无效的解决办法
  7. 神仙打架!传言阿里 P10 赵海平被 P11 多隆判定 3.25 离职,如何评价阿里 P10 赵海平对王垠的面试?...
  8. xml转matlab目标检测,将Cityscape转换为PASACAL VOC格式的目标检测数据集
  9. 台式计算机操作系统的安装,台式电脑重装系统步骤图解
  10. iPhone各种尺寸的分辨率