MyBatis实现多表的一对一、一对多、多对多关联查询

您所在的位置:网站首页 mybatis一对一映射标签 MyBatis实现多表的一对一、一对多、多对多关联查询

MyBatis实现多表的一对一、一对多、多对多关联查询

2024-07-12 15:30| 来源: 网络整理| 查看: 265

MyBatis是一个基于数据库映射的框架,本文将介绍如何使用MyBatis处理多张数据库表之间的关联关系。

1、一对一查询

一对一外键关联的配置比较简单,以公民实体对象和身份证实体对象为例,在表tab_people(公民表)中添加一个字段“card_id”,作为该表的外键,同时需要保证该字段的唯一性,否则就不是一对一映射关系了,而是一对多映射关系。表tab_people和tab_idcard(身份证表)之间的关联关系如下图所示。

【示例】一对一关联,获取公民信息与身份证号码。

(1)在MySQL数据库创建tab_people表和tab_idcard表,并添加相关数据。

-- 判断数据表是否存在,存在则删除 DROP TABLE IF EXISTS tab_people; DROP TABLE IF EXISTS tab_idcard; -- 创建“身份证信息”数据表 CREATE TABLE IF NOT EXISTS tab_idcard ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '身份证ID', idCard_code VARCHAR(45) COMMENT '身份证号码' ) COMMENT = '身份证信息表'; -- 创建“公民信息”数据表 CREATE TABLE IF NOT EXISTS tab_people ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '公民ID', NAME VARCHAR(45) NOT NULL COMMENT '公民名称', sex VARCHAR(2) COMMENT '公民性别', age INT COMMENT '公民年龄', card_id INT UNIQUE COMMENT '身份证ID', -- 创建外键约束 FOREIGN KEY fk_card_id (card_id) REFERENCES tab_idcard(id) ) COMMENT = '公民信息表'; -- 添加数据 INSERT INTO tab_idcard(idCard_code) VALUE('123456789'); INSERT INTO tab_people(NAME,sex,age,card_id) VALUES('pan_junbiao的博客','男',32,1);

(2)创建名称为People.java公民信息的持久化类。

package com.pjb.mybatis.po; /** * 公民信息的持久化类 * @author pan_junbiao **/ public class People { private int id; //公民ID private String name; //公民名称 private String sex; //公民性别 private int age; //公民年龄 private IDcard idcard; //关联的身份证对象 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public IDcard getIdcard() { return idcard; } public void setIdcard(IDcard idcard) { this.idcard = idcard; } }

(3)创建名称为IDcard.java身份证信息的持久化类。

package com.pjb.mybatis.po; /** * 身份证信息的持久化类 * @author pan_junbiao **/ public class IDcard { private int id; //身份证ID private String idCardCode; //身份证号码 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getIdCardCode() { return idCardCode; } public void setIdCardCode(String idCardCode) { this.idCardCode = idCardCode; } } 1.1 方式一:SQL表关联语句

使用SQL表关联语句,获取公民信息,同时关联获取身份证信息。

SQL映射信息如下:

SELECT p.id AS people_id ,p.NAME ,p.sex ,p.age ,c.id AS card_id ,c.idCard_code FROM tab_people p LEFT JOIN tab_idcard c ON p.card_id = c.id WHERE p.id = #{peopleId}

编写执行方法:

/** * 一对一查询:获取公民信息与关联的身份证信息 * @author pan_junbiao */ @Test public void getPeopleAndIdcard() { DataConnection dataConnection = new DataConnection(); SqlSession sqlSession = dataConnection.getSqlSession(); People people = sqlSession.selectOne("test.getPeopleAndIdcard", 1); if (people != null) { System.out.println("---------------1、公民信息--------------------"); System.out.println("公民编号:" + people.getId()); System.out.println("公民名称:" + people.getName()); System.out.println("公民性别:" + people.getSex()); System.out.println("公民年龄:" + people.getAge()); //获取关联的身份证信息信息 System.out.println("---------------2、身份证信息信息---------------"); IDcard idCard = people.getIdcard(); if(idCard!=null) { System.out.println("身份证ID:" + idCard.getId()); System.out.println("身份证号码:" + idCard.getIdCardCode()); } } sqlSession.close(); }

执行结果:

1.2 方式二:延迟加载

如果不使用表的关联关系,而是通过两个SQL查询语句来分别获取公民信息、身份证信息。

首先开启延迟加载,在MyBatis的全局配置文件SqlMapConfig.xml(mybatis-config.xml)中的标签中添加“开启延迟加载”配置信息:

修改获取公民信息的配置信息,如下:

SELECT * FROM tab_people WHERE id = #{id} SELECT * FROM tab_idcard WHERE id = #{id}

执行结果:

 

2、一对多查询

在日常开发中一对多查询是常见的,也是业务中十分重要的部分。下面将以生产商对象(类Factory)与产品对象(类Product)为例,讲解MyBatis的一对多关联。类Factory与类Product的关联关系如下图。

【示例】建立生产商与产品对象对象的一对多关联,并利用映射关系查询完整的产品信息。

(1)在MySQL数据库创建tab_factory表和tab_product表,并添加相关数据。

-- 创建“生产商信息”数据表 CREATE TABLE IF NOT EXISTS tab_factory ( factory_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '生产商ID', NAME VARCHAR(20) NOT NULL COMMENT '生产商名称' ) COMMENT = '生产商信息表'; -- 创建“产品信息”数据表 CREATE TABLE IF NOT EXISTS tab_product ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '产品ID', NAME VARCHAR(20) NOT NULL COMMENT '产品名称', price DECIMAL(9,2) NOT NULL COMMENT '产品价格', factory_id INT COMMENT '生产商ID' ) COMMENT = '产品信息表'; -- 添加数据 INSERT INTO tab_factory(NAME) VALUES('华为公司'); INSERT INTO tab_product(NAME,price,factory_id) VALUES('华为手机',1299,1); INSERT INTO tab_product(NAME,price,factory_id) VALUES('华为路由器',699,1);

(2)创建名称为Product.java产品信息的持久化类。

package com.pjb.mybatis.po; import java.math.BigDecimal; /** * 产品信息的持久化类 * @author pan_junbiao **/ public class Product { private int id; //产品ID private String name; //产品名称 private BigDecimal price; //产品价格 private int factoryId; //生产商ID public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getPrice() { return price; } public void setPrice(BigDecimal price) { this.price = price; } public int getFactoryId() { return factoryId; } public void setFactoryId(int factoryId) { this.factoryId = factoryId; } }

(3)创建名称为Factory.java生产商信息的持久化类。

package com.pjb.mybatis.po; import java.util.List; /** * 生产商信息的持久化类 * @author pan_junbiao **/ public class Factory { private int factoryId; //生产商ID private String name; //生产商名称 private List productList; //产品列表 public int getFactoryId() { return factoryId; } public void setFactoryId(int factoryId) { this.factoryId = factoryId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getProductList() { return productList; } public void setProductList(List productList) { this.productList = productList; } } 2.1 方式一:SQL表关联语句

使用SQL表关联语句,获取生产商信息,同时关联获取产品列表。

SQL映射信息如下:

SELECT f.factory_id ,f.name AS factory_name ,p.id AS product_id ,p.name AS product_name ,p.price FROM tab_factory f LEFT JOIN tab_product p ON f.factory_id = p.factory_id WHERE f.factory_id = #{factoryId}

编写执行方法:

/** * 一对多查询:获取生产商信息与关联的产品列表 * @author pan_junbiao */ @Test public void getFactoryAndProductList() { DataConnection dataConnection = new DataConnection(); SqlSession sqlSession = dataConnection.getSqlSession(); Factory factory = sqlSession.selectOne("test.getFactoryAndProductList",1); if (factory != null) { System.out.println("---------------1、生产商信息信息--------------"); System.out.println("生产商编号:" + factory.getFactoryId()); System.out.println("生产商名称:" + factory.getName()); //获取关联的产品信息信息 System.out.println("---------------2、产品信息信息---------------"); List productList = factory.getProductList(); if(productList!=null && productList.size()>0) { for(Product product : productList) { System.out.println("产品编号:" + product.getId()); System.out.println("产品名称:" + product.getName()); System.out.println("产品价格:" + product.getPrice()); System.out.println("生产商编号:" + product.getFactoryId()); System.out.println("-------------------"); } } } sqlSession.close(); }

执行结果:

2.2 方式二:延迟加载

修改SQL映射信息如下:

SELECT * FROM tab_factory WHERE factory_id = #{factoryId} SELECT * FROM tab_product WHERE factory_id = #{factoryId}

执行结果:

 

3、多对多查询

多对多关联关系是比较特殊的一种关联关系,它与一对一和一对多关联关系不同,需要通过另外的一张表保存多对多的映射关系。下面将以应用系统中的权限分配为例讲解多对多的关联关系,例如用户可以拥有多个系统的操作权限,而一个权限又可以被赋予多个用户,这就是典型的多对多关联映射关系。其中用户表(tab_user)和权限表(tab_user)的表关系如下图所示。

说明:由于多对多关联关系的查询对第3个表进行反复查询,在一定程度上会影响系统的性能效率,所以在应用中尽量少使用多对多关联关系的表结果。

【示例】建立用户对象与权限对象的多对多关联关系,查询用户admin所拥有的权限,以及权限“新闻管理”被赋予了哪些用户。

(1)在MySQL数据库创建用户表(tab_user)、权限表(tab_role)和映射表(tab_mapping),并添加相关数据。

-- 判断数据表是否存在,存在则删除 DROP TABLE IF EXISTS tab_user; DROP TABLE IF EXISTS tab_role; DROP TABLE IF EXISTS tab_mapping; -- 创建“用户信息”数据表 CREATE TABLE IF NOT EXISTS tab_user ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户ID', NAME VARCHAR(45) NOT NULL COMMENT '用户名称' ) COMMENT = '用户信息表'; -- 创建“权限信息”数据表 CREATE TABLE IF NOT EXISTS tab_role ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '权限ID', role_name VARCHAR(45) NOT NULL COMMENT '权限名称' ) COMMENT = '权限信息表'; -- 创建“映射信息”数据表 CREATE TABLE IF NOT EXISTS tab_mapping ( id INT AUTO_INCREMENT PRIMARY KEY COMMENT '映射ID', user_id INT COMMENT '用户Id', role_id INT COMMENT '权限Id' ) COMMENT = '映射信息表'; -- 添加数据 INSERT INTO tab_user(NAME) VALUES('admin'),('pan_junbiao的博客'); INSERT INTO tab_role(role_name) VALUES('系统管理员'),('新闻管理员'),('广告管理员'); INSERT INTO tab_mapping(user_id,role_id) VALUES(1,1),(1,2),(1,3),(2,2),(2,3);

(2)创建名称为User.java用户信息的持久化类。

package com.pjb.mybatis.po; import java.util.List; /** * 用户信息的持久化类 * @author pan_junbiao **/ public class User { private int id;//用户ID private String name;//用户名称 private List roleList;//引用的权限实体对象集合 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getRoleList() { return roleList; } public void setRoleList(List roleList) { this.roleList = roleList; } }

(3)创建名称为Role.java权限信息的持久化类。

package com.pjb.mybatis.po; /** * 权限信息的持久化类 * @author pan_junbiao **/ public class Role { private int id;//权限ID private String roleName;//权限名称 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } }

(4)编写SQL映射信息。

SELECT u.id AS user_id ,u.name AS user_name ,r.id AS role_id ,r.role_name FROM tab_user u, tab_role r, tab_mapping m WHERE u.id = m.user_id AND r.id = m.role_id

(5)编写执行方法。

/** * 多对多查询:获取用户信息与关联的权限列表 * @author pan_junbiao */ @Test public void getUserAndRole() { DataConnection dataConnection = new DataConnection(); SqlSession sqlSession = dataConnection.getSqlSession(); List userList = sqlSession.selectList("test.getUserAndRole"); if(userList!=null && userList.size()>0) { //遍历用户列表 for(User user : userList) { System.out.println("用户编号:" + user.getId()); System.out.println("用户名称:" + user.getName()); //获取权限列表 List roleList = user.getRoleList(); if(roleList!=null && roleList.size()>0) { System.out.print("用户拥有的权限:"); for (Role role : roleList) { System.out.print(role.getRoleName()+";"); } } System.out.println("\n-----------------------------------------------"); } } sqlSession.close(); }

执行结果:

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3