简介
多表之间的关系
- 一对多
- 用户 ——> 订单、订单、订单、订单
- 多对一(一对一)
- 订单、订单、订单、订单 ——> 用户
- 单个订单 ——> 用户
- 一对一
- 中国公民——>身份证
- 多对多
- 语文老师、数学老师、英语老师——>小明、小红、小黑、小绿
MyBatis中多表之间的关系
- 本次案例主要以最为简单的用户(User)、账户(Account)、角色(Role)的模型来分析Mybatis多表关系。
- 用户为User 表,账户为Account表。
- 一对多关系
- 一个用户(User)可以开设多个账户(Account)
- 从查询 用户信息(User) 出发,关联查询 账户信息(Account)属于一对多查询
- 一个用户(User)可以开设多个账户(Account)
- 一对一关系(多对一)
- 多个账户(Account)可以对应一个用户(User)
- 单个账户(Account)只能属于一个用户(User)
- 从查询 账户信息(Account) 出发,关联查询 用户信息(User)属于一对一查询
- 多对多关系
- 一个用户(User)可以拥有多个角色(Role)
- 一个角色(Role)可以赋予多个用户(User)
- 多对多关系其实我们看成是双向的一对多关系。
- 一对多关系
- 用户为User 表,账户为Account表。
目录结构
- src
- main
- java
- cn.water.dao
- M2MDao.java(多对多 持久层接口)
- O2MDao.java(一对多 持久层接口)
- O2ODao.java(一对一 持久层接口)
- cn.water.domain
- M2M_Role.java(多对多 实体类)
- M2M_User.java(多对多 实体类)
- O2M_Account.java(一对多 实体类)
- O2M_User.java(一对多 实体类)
- O2O_Account.java(一对一 实体类)
- O2O_AccountUser.java(一对一 实体类)
- O2O_User.java(一对一 实体类)
- cn.water.dao
- resources
- cn.water.dao
- M2MDao.xml(多对多 映射配置文件)
- O2MDao.xml(一对多 映射配置文件)
- O2ODao.xml(一对一 映射配置文件)
- SqlMapConfig.xml(MyBatis主配置文件)
- jdbcConfig.properties(数据库连接信息文件)
- cn.water.dao
- java
- test
- java.cn.water
- MybatisTest.java(测试类)
- java.cn.water
- main
MyBatis主配置文件
SqlMapConfig.xml
1 |
|
数据库连接信息文件
jdbcConfig.properties
1 | jdbc.driver=com.mysql.jdbc.Driver |
实体类
M2M_Role.java
1 | package cn.water.domain; |
M2M_User.java
1 | package cn.water.domain; |
O2M_Account.java
1 | package cn.water.domain; |
O2M_User.java
1 | package cn.water.domain; |
O2O_Account.java
1 | package cn.water.domain; |
O2O_AccountUser.java
1 | package cn.water.domain; |
O2O_User.java
1 | package cn.water.domain; |
持久层
M2MDao.java
1 | package cn.water.dao; |
O2MDao.java
1 | package cn.water.dao; |
O2ODao.java
1 | package cn.water.dao; |
映射配置文件
M2MDao.xml
1 |
|
O2MDao.xml
1 |
|
O2ODao.xml
1 |
|
测试类
MyBatisTest.java
1 | package cn.water; |
一对一查询
- 从查询 账户信息(Account) 出发,关联查询 用户信息(User)
结果集
- 当我们查询多个表的时候,我们就需要考虑考虑结果集封装类的问题了。
- 例如,我们需要查询用户(User)的 username字段 和 address字段 以及账户(Account)的 所有字段。
- 方法一:根据查询方式,将实体类设置为变量。
- 方法二:根据查询结果,创建新的实体类。
方法一:将实体类设置为变量
- 在账户类(Account)直接将 用户类(User)设置为变量,于是账户类即封装了账户信息,又封装了用户信息。
- 以持久层接口的方法 find01 为案例,查询 Account.uid 与 User.id 相等的所有 Account信息和 User信息。
用户类
1 | public class O2O_User implements Serializable { |
账户类(结果集封装类)
- 将 用户类(User)设置为变量
1 | public class O2O_Account implements Serializable { |
持久层接口
1 | List<O2O_Account> findAll01 (); |
映射配置文件
- 使用resultMap,定义专门的resultMap用于映射一对一查询结果。
1 | <!-- 【次表:Account】 --> |
测试类
1 |
|
运行结果
1 | O2O_Account{ |
方法二:创建新的实体类
创建 账户子类(AccountUser),由于继承关系我们可以封装账户信息,于是我们只用再设置 usernam变量 和 address变量就可以封装用户信息了。
- 以持久层接口的方法 find02 为案例,查询 Account.uid 与 User.id 相等的所有 Account信息和 User的usename 和 address信息。
用户类
1 | public class O2O_User implements Serializable { |
账户类
1 | public class O2O_Account implements Serializable { |
账户子类(结果集封装类)
- 调用父类的toString方法
1 | public class O2O_AccountUser extends O2O_Account implements Serializable { |
持久层接口
1 | List<O2O_AccountUser> findAll02 (); |
映射配置文件
1 | <!-- 多表查询 --> |
测试类
1 |
|
运行结果
1 | O2O_Account{id=1, uid=46, money=1000.0, user=null} O2O_AccountUser{username='老王', address='北京'} |
一对多查询
- 从查询 用户信息(User) 出发,关联查询 账户信息(Account)
- 用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息
查询出来,我们想到了左外连接查询比较合适。
用户类
- 一对多关系映射:主表实体类 应该包含 从表实体类的集合引用
1 | public class O2M_User implements Serializable { |
账户类
1 | public class O2M_Account implements Serializable { |
持久层接口
1 | List<O2M_User> findAll (); |
映射文件
1 | <!-- 【主表:User】 --> |
测试类
1 |
|
测试结果
1 | O2M_User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京', accounts=[O2M_Account{id=41, uid=null, money=null}]} |
多对多查询
- 多对多关系其实我们看成是双向的一对多关系。
用户类
- 多对多关系映射:两个实体类应该包含彼此的集合引用
1 | public class M2M_User implements Serializable { |
角色类
- 多对多关系映射:两个实体类应该包含彼此的集合引用
1 | public class M2M_Role implements Serializable { |
持久层接口
1 | List<M2M_Role> findAll(); |
映射文件
1 | <!-- 【Role表】 --> |
测试类
1 |
|
测试结果
1 | M2M_Role{roleId=1, roleName='院长', roleDesc='管理整个学院', users=[M2M_User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京', roles=null}, M2M_User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙', roles=null}]} |
比较:O2O O2M
一对一
实体类
用户类
- id
- username
- birthday
- sex
- address
账户类
- id
- uid
- money
- user
映射配置文件
- association标签
- javaType属性
1 | <!-- 【次表:Account】 --> |
一对多
实体类
用户类
- id
- username
- birthday
- sex
- address
- LIst<Account>
账户类
- id
- uid
- money
映射配置文件
- collection标签
- ofType属性
1 | <!-- 【主表:User】 --> |