Java Web基础入门第六十三讲 使用JDBC进行多表操作

前言:在使用JDBC进行多表操作之前,建议多看看我这篇博客《Java Web基础入门第四十四讲 数据库表的设计》

使用JDBC操作一对多或多对一关系的数据库表

我们以部门和员工的关系来说明使用JDBC是如何操作一对多或多对一关系的数据库表的。
首先,使用如下SQL建表语句在数据库中创建department表和employee表。

create table department
(
    id varchar(40) primary key,
    name varchar(40)
);

create table employee
(
    id varchar(40) primary key,
    name varchar(40),
    salary double,
    department_id varchar(40),
    constraint department_id_FK foreign key(department_id) references department(id)
);

然后,在cn.liayun.domain包下创建两个封装数据的JavaBean——Department.java和Employee.java。

  • Department类的具体代码如下:

    package cn.liayun.domain;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Department {
    	
    	private String id;
    	private String name;
    	private Set employees = new HashSet();
    	
    	public Set getEmployees() {
    		return employees;
    	}
    	public void setEmployees(Set employees) {
    		this.employees = employees;
    	}
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    }
    
  • Employee类的具体代码如下:

    package cn.liayun.domain;
    
    public class Employee {
    	private String id;
    	private String name;
    	private double salary;
    	private Department department;
    	
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public double getSalary() {
    		return salary;
    	}
    	public void setSalary(double salary) {
    		this.salary = salary;
    	}
    	public Department getDepartment() {
    		return department;
    	}
    	public void setDepartment(Department department) {
    		this.department = department;
    	}
    }
    

这时,部门和员工对象的关系和部门表和员工表在数据库里的关系如下图:
在这里插入图片描述
最后,还要在cn.liayun.dao包下创建一个类——DepartmentDao.java,下面用它来操作数据库中的部门表和员工表。

向部门表中新增一个部门,并在该部门下面新增几个员工

在这里插入图片描述
我们在应用程序中加入了DBCP连接池,还有关于JdbcUtils类怎么写,可以参考我的笔记《Java Web基础入门第六十一讲 Apache DBUtils框架的学习》

查询某部门的基本信息以及该部门下的所有员工信息

在这里插入图片描述
在实际开发里面,关于一对多和多对一,有一个设计原则:尽量避免去使用一对多这种关系,而应该多使用多对一这种关系。但有时候是不可避免的,例如,订单和订单项就是一对多这种关系,一个订单里面有多个订单项,在显示订单的时候一定要显示多方的数据,即订单项,这时候我们就必须设计这种关系了。如果你没有设计这种关系,这时候从数据库里面找出订单的基本信息,人家一看订单,只能看到订单的基本信息,不能看到订单项,这是不行的。如果这时候不可避免要设计这种关系(一对多这种关系),如果订单项有上千万条的数据,千万不能直接将其找出来,一定要采用分页的方式去找。
在一方记住了多方,在多方也记住了一方,我们这样设计就是双向的关联,在实际开发里面,这种双向的关联是不推荐使用的!而且一对多这种关系最好就不要设计,即不要在一方记住了多方,如果你设计了,在找出一方的数据时就要取多方的数据,如果多方的数据超多的话,很容易导致内存溢出。那么在一方不用记住多方,而在多方记住了一方,我们这样设计就是单向的关联。假设一个部门下面有10万个员工,你首先找部门的信息,然后就要将这10万个员工全部找出来存放在List集合里面,那内存就蹦了。所以在实际开发过程中,在写一对多的find方法时,找出一方的数据,再找多方的数据,你这时候千万要小心,一定要注意多方的数据多不多,如果多方的数据多的话,千万不能直接将其找出来,要采用分页的方式去找

删除某部门

我们可采用两种方式来删除某部门,其中第一种方式如下:
在这里插入图片描述
第二种方式:数据库支持级联,如果设置了级联,只需要根据id删除部门即可,由于你设置了级联,数据库系统会自动把employee表的外键列department_id置空。首先,删除employee表的外键约束:
在这里插入图片描述
再在employee表的外键列department_id设置级联:
在这里插入图片描述
SET NULL仅仅把employee表的外键列department_id置空。我们还可以这样为employee表的外键列department_id设置级联:
在这里插入图片描述
CASCADE表示部门被删除时,所有的员工都会被删掉(主表一删,从表中的所有数据就都要删掉)。
在employee表的外键列department_id设置好级联之后,删除部门的代码就变为:
在这里插入图片描述
编写完DepartmentDao类的代码之后,我们来测试一把,测试代码为:

package cn.liayun.service;

import java.sql.SQLException;

import org.junit.Test;

import cn.liayun.dao.DepartmenDao;
import cn.liayun.dao.TeacherDao;
import cn.liayun.domain.Department;
import cn.liayun.domain.Employee;
import cn.liayun.domain.Student;
import cn.liayun.domain.Teacher;

public class BService {
	
	@Test
	public void add() throws SQLException {
		Department d = new Department();
		d.setId("10001");
		d.setName("研发部");
		
		Employee e1 = new Employee();
		e1.setId("1");
		e1.setName("李阿昀");
		e1.setSalary(10000);
		
		Employee e2 = new Employee();
		e2.setId("2");
		e2.setName("李燕琼");
		e2.setSalary(4000);
		
		d.getEmployees().add(e1);
		d.getEmployees().add(e2);
		
		DepartmenDao dao = new DepartmenDao();
		dao.add(d);
	}
	
	@Test
	public void find() throws SQLException {
		DepartmenDao dao = new DepartmenDao();
		Department d = dao.find("10001");
		System.out.println(d);
	}
	
	@Test
	public void delete() throws SQLException {
		DepartmenDao dao = new DepartmenDao();
		dao.delete("10001");
	}

}

使用JDBC操作多对多关系的数据库表

我们以老师和学生的关系来说明使用JDBC是如何操作多对多关系的数据库表的。
首先,使用如下SQL建表语句在数据库中创建teacher表和student表以及teacher_student表(中间表)。

create table teacher 
(
    id varchar(40) primary key,
    name varchar(40),
    salary double
);

create table student 
(
    id varchar(40) primary key,
    name varchar(40)
);

create table teacher_student 
(
    teacher_id varchar(40),
    student_id varchar(40),
    primary key(teacher_id, student_id),
    constraint teacher_id_FK foreign key(teacher_id) references teacher(id),
    constraint student_id_FK foreign key(student_id) references student(id)
);

数据库表结构如下图:
在这里插入图片描述
然后,在cn.liayun.domain包下创建两个封装数据的JavaBean——Teacher.java和Student.java。

  • Teacher类的具体代码如下:

    package cn.liayun.domain;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Teacher {
    	private String id;
    	private String name;
    	private double salary;
    	private Set students = new HashSet();
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public double getSalary() {
    		return salary;
    	}
    	public void setSalary(double salary) {
    		this.salary = salary;
    	}
    	public Set getStudents() {
    		return students;
    	}
    	public void setStudents(Set students) {
    		this.students = students;
    	}
    	
    }
    
  • Student类的具体代码如下:

    package cn.liayun.domain;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Student {
    	private String id;
    	private String name;
    	private Set teachers = new HashSet();
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public Set getTeachers() {
    		return teachers;
    	}
    	public void setTeachers(Set teachers) {
    		this.teachers = teachers;
    	}
    	
    }
    

最后,还要在cn.liayun.dao包下创建一个类——TeacherDao.java,用它来操作数据库中的老师表、学生表以及中间表。

向老师表中新增一个老师,并在该老师下面新增几个学生

在这里插入图片描述

查询某老师的基本信息以及该老师下的所有学生信息

此时涉及到多表查询。
在这里插入图片描述

删除某老师

首先,只在teacher_student表的外键列teacher_id上设置级联。
在这里插入图片描述
删除老师的代码为:
在这里插入图片描述
此时删除teacher表中的某一条记录(例如id为1的老师),那么在teacher_student中间表中teacher_id为1的记录都被删掉了,而student表是不受任何影响的。
现在我们不仅在teacher_student表的外键列teacher_id上设置级联,还在teacher_student表的外键列student_id上也设置级联,如下:
在这里插入图片描述
此时删除teacher表中的某一条记录(例如id为1的老师),那么在teacher_student中间表中teacher_id为1的记录都被删掉了,而student表还是不会受任何影响。
温馨提示:在学Hibernate框架的时候,要设置级联删除时候,有一方要放弃关系的维护,不然会陷入死循环。

总结

  • 不管Java的对象存在何种关系,反映到关系型数据库中,都是使用外键表示记录(即对象)的关联关系;
  • 设计Java对象如涉及到多个对象相互引用,要尽量避免使用一对多,或多对多关系,而应使用多对一描述对象之间的关系(或使用延迟加载的方式)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李阿昀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值