级联查询

本文讲解了如何通过Java编程实现MySQL连接,创建学生和信息表,设计实体映射,并演示了级联查询的一对一关系。涉及工具类DBTools的使用,以及实体类Student和Info的创建,接口设计,以及InfoDaoImpl的实现。
摘要由CSDN通过智能技术生成

一对一

步骤: 导mysql 的 jar包,及工具类
自己创建连接数据库的工具类 DBTools
通过面向接口设计程序的方式来编程

SQL创建表

  1. 创建学生表
    create table student(
    sid int primary key auto_increment,
    stuName varchar(22),
    address varchar(22));
  2. 创建信息表
    create table info(
    id int primary key auto_increment,
    code varcahr(22),
    address varchar(22),
    sid int,
    foreign key(sid) references student(sid));
    表之间的关系是 一对一。
    在这里插入图片描述

创建实体并映射

  1. 并非通过在实体中添加不属于本实体的属性来映射的 只是为了方便通过本实体通过 访问器的方式去访问主表。 创建实体是直接代码表示,且从表中有外键。
  2. toString()只是打印本类的属性和方法 不能添加 非本类的属性 及使用toString要在映射之前。
  3. 每次映射后 ,及 Info表中添加private Student student;属性和改访问器 这是通过从表查询主表的时候用的 若不考虑逻辑;通过学生查询他的身份证,则需要返回的类型是Student 在通过访问器的方式返回 info实体。
  4. 映射在从表和主表都可以,取决于
    通过主表找从表 映射在主表
    通过从表找主表 映射在从表
  5. 面向接口编程的思想
    一. 实体表
 package www.oracle.vo;

public class Student {
	private Integer sid;
	private String stuName;
	private String password;
	private Info info;
	
	public Info getInfo() {
		return info;
	}
	public void setInfo(Info info) {
		this.info = info;
	}
	public Integer getSid() {
		return sid;
	}
	public void setSid(Integer sid) {
		this.sid = sid;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", stuName=" + stuName + ", password=" + password + "]";
	}
	
	

}

package www.oracle.vo;

public class Info {
	private Integer id;
	private String code;
	private String address;
	private Integer sid;
	private Student studnet;
	
	public Student getStudnet() {
		return studnet;
	}
	public void setStudnet(Student studnet) {
		this.studnet = studnet;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public Integer getSid() {
		return sid;
	}
	public void setSid(Integer sid) {
		this.sid = sid;
	}
	@Override
	public String toString() {
		return "Info [id=" + id + ", code=" + code + ", address=" + address + ", sid=" + sid + "]";
	}
	
	

}

二.接口

package www.util.dao;

import www.oracle.vo.Info;

public interface InfoDao {
	public Info getStudentByInfoCode(String code) throws Exception;

}

三.接口的实现类

package www.util.daoImpl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import www.oracle.util.DBTools;
import www.oracle.vo.Info;
import www.oracle.vo.Student;
import www.util.dao.InfoDao;
// 建立级联查询 一对一  是通过一个类中包含一个私有类, 通过从表(或主表)查询主表(从表),返回值类型是从表(主表)的类型;从表的类型在创建对象获得他的属性 主表 及  info.getStudent() 来获取主表的对象
									//  通过 主表查询从表,返回的类型是主表的类型;在通过返回的对象来获得从表的属
        //-----重要:级联查询是通过 俩实体表中互相映射来模拟外键的
      /*1. 通过 Info 查询  Student    返回一个Info实体;在 Info a=new Info();  a.getStudent()  获取Stduent实体
       *2. 通过 Student 查询 Info    返回一个 Student实体  在 Student a=new Student();    a.getInfo();的方式获取 Info实体
       * 
       * */
public class InfoDaoImpl implements InfoDao  {

	@Override
	public Info getStudentByInfoCode(String code) throws Exception {
		// TODO Auto-generated method stub
		String sql="select * from info i inner join student s on i.sid=s.sid where i.`code` = ?";
		
		Connection conn= DBTools.getConnection();
		
		PreparedStatement ps= conn.prepareStatement(sql);
		
		ps.setString(1, code);
		ResultSet  rs=ps.executeQuery();
		Info info=null;
		Student student=null;
		while(rs.next()) {
			info =new Info();
			student= new Student();
			info.setAddress(rs.getString("address"));
			info.setCode(rs.getString("code"));
			info.setId(rs.getInt("id"));
			info.setSid(rs.getInt("sid"));
			student.setPassword(rs.getString("password"));
			student.setSid(rs.getInt("sid"));
			student.setStuName(rs.getString("stuName"));
			info.setStudnet(student);
		}
		return info;
	}

	

	

}
//TODO Auto-generated method stub
		// TODO Auto-generated method stub
				// TODO Auto-generated method stub
						// 根据 info表找学生信息  外键在从表info中  一般逻辑上都是从表找主表  通过外键查询主表 
						/*   一对一  外键在主表或从表都可
						 * 	select  * from info a        从表 info   a
						 * 		inner join student b     主表 student   b
						 * 		on a.sid=b.sid           可以看出是等值连接
						 *      where a.`code`='9527';   查询条件根据从表的`code` 来查找 
						 * 
						 * 
						 * */ 

四. 测试类

package www.oracle.test;

import org.junit.Test;

import www.oracle.vo.Info;
import www.oracle.vo.Student;
import www.util.dao.InfoDao;
import www.util.daoImpl.InfoDaoImpl;

public class TestInfo {
	InfoDao info =new InfoDaoImpl();
	// 根据info表 查询 学生  返回的是 info的类型  通过info对象来获取本类中的学生属性   这是映射  要注意的是, 表实体类内的toString不能打印映射属性的  但是可以打印外键
	//   在赋值的代码中可以看出  通过info表查询学生 不需要在 学生实体中加映射;因为映射就是为了通过改实体获得映射对象的实体信息  故 不需要在Student实体中写 private Info info;这行映射代码
	@Test
	public void  getInfo() throws Exception {
		String code="9567";
		Info a=info.getStudentByInfoCode(code);
		Student student=a.getStudnet();
		System.out.println(student);
	}

}

总结–模型层

在这里插入图片描述
www.oracle.vo 实体包
www.oracle.util 工具包
www.oracle.dao 接口包
www.oracle.daoImpl 实现类包
www.oracle.test 测试包
www.oracle.constant 常量包

  1. 需要手动导入 mysql的jar包来用,这是官方写的 我们不知道内部源码 直接用
  2. 测试包好导入 直接就导入了 不需要像jar包那样麻烦
  3. 最难的是实现类怎么写
  4. sql语句的级联查询 一般根据谁查谁就是主表
    select * from info a -----------------主表
    inner join studnet b ------------------从表
    on a.sid=b.sid -----------------等职查询
    where a.code=‘ ’;------------------

一对多中的反向是一对一

order不加着重 关键字当作表来使用

理解:一对多是指多方中的一个也是和这个主表有联系 及一对一。

-----------------------------重要 ----------------------
sql语法错误: 以默认关键字不加着重的方式来当作表查询
select * from order o
inner join student s
on o.sid=s.sid -----------------------------正确
where o.oid=5;

select * from order o inner join student s on o.sid=s.sid where o.oid= ? ------------------------------------------------------------------------------------ 错误
错误代码

package www.oracle.daoImpl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import www.oracle.dao.OrderDao;
import www.oracle.util.DBTools;
import www.oracle.vo.Order;
import www.oracle.vo.Student;

public class OrderDaoImpl  implements OrderDao {

	@Override
	public Order getStudentByOrder(int id) throws Exception {
		// TODO Auto-generated method stub                                     //-------------------------------重要
		String sql="select * from order o inner join student s on o.sid=s.sid where o.oid= ?";// 注意 根据order表找学生 是一对一  应根据的查询位置是 order表的id才可以
		Connection conn=DBTools.getConnection();                                              //  老师写的一对多 是根据学生找订单 查询位置自然hi是 根据学生的sid来找 及 where sid=s.sid=?才可以
		PreparedStatement ps=conn.prepareStatement(sql);                                      //  order没有加着重  所i一写sql语句环视在 Nevicat里写把 有提示
		ps.setInt(1, id);
		ResultSet rs=ps.executeQuery();
		Order order =null;
		Student student =null;
		while(rs.next()) {
			order=new Order();
			student =new Student();
			order.setCode(rs.getString("code"));
			order.setCreateTime(rs.getTimestamp("createTime"));
			order.setOid(rs.getInt("oid"));
			order.setPrice(rs.getDouble("price"));
			
			student.setPassword(rs.getString("password"));
			student.setSid(rs.getInt("sid"));
			student.setStuName(rs.getString("stuName"));
			order.setStudent(student);
			
			
			
		}
		return order;
		
	
		
}
}
  1. 创建表
    不知道如何用SQL语言插入 TimeStamp时间变量
    create table order(
    oid int primary key auto_increment,
    code varchar(22),
    price DOUBLE,
    createTime TimeStamp, ---------TimeStamp自动获取数据库时间的时分秒
    sid int,
    foreign key(sid) references student(sid)); ------------------------ 外键

create table student(
sid int primary key auto_increment,
stuName varchar(22),
address varcahr(22));

表模型
在这里插入图片描述
2. 创建实体

package www.oracle.vo;

import java.util.List;

public class Student {
	private Integer sid;
	private String stuName;
	private String password;
	private List<Order> order;
	public Integer getSid() {
		return sid;
	}
	public void setSid(Integer sid) {
		this.sid = sid;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", stuName=" + stuName + ", password=" + password + "]";
	}
	
	
	

}
package www.oracle.vo;

import java.sql.Timestamp;

public class Order {
	private Integer oid;
	private String code;
	private Double price;
	private Timestamp createTime;
	private Student student;
	
	public Student getStudent() {
		return student;
	}
	public void setStudent(Student student) {
		this.student = student;
	}
	public Integer getOid() {
		return oid;
	}
	public void setOid(Integer oid) {
		this.oid = oid;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	public Double getPrice() {
		return price;
	}
	public void setPrice(Double price) {
		this.price = price;
	}
	public Timestamp getCreateTime() {
		return createTime;
	}
	public void setCreateTime(Timestamp createTime) {
		this.createTime = createTime;
	}
	@Override
	public String toString() {
		return "Order [oid=" + oid + ", code=" + code + ", price=" + price + ", createTime=" + createTime + "]";
	}
	
	
	

}
  1. 接口设计
package www.oracle.dao;

import www.oracle.vo.Order;

public interface OrderDao {
	// 一对一, 一对多的反向   但是业务上一般是 学生查看自己点了哪些订单
	public Order getStudentByOrder(int id) throws Exception;
	

}
  1. 导mysql的jar包 并自己设计连接数据库的工具类
    在这里插入图片描述
    设计 DBTools工具类
package www.oracle.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DBTools {
	private static final String URL="jdbc:mysql://localhost:3306/test?characterEncoding=UTF8";
	private static final String USER="root";
	private static final String PASSWORD="root";
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static Connection getConnection() throws SQLException {
		Connection conn=null;
		conn =DriverManager.getConnection(URL,USER,PASSWORD);
		return conn;
	}
	public static void close(Statement stat, ResultSet rs, Connection conn) {
		try {
		if(rs!=null) {
			rs.close();
		}
		if(conn !=null) {
				conn.close();
		}
		if(stat !=null) {
			stat.close();
		}
	
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
}
	}
  1. 接口的实现类
package www.oracle.daoImpl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import www.oracle.dao.OrderDao;
import www.oracle.util.DBTools;
import www.oracle.vo.Order;
import www.oracle.vo.Student;

public class OrderDaoImpl  implements OrderDao {

	@Override
	public Order getStudentByOrder(int id) throws Exception {
		// TODO Auto-generated method stub                                     //-------------------------------重要
		String sql="select * from `order` o inner join student s on o.sid=s.sid where o.oid= ?";// 注意 根据order表找学生 是一对一  应根据的查询位置是 order表的id才可以
		Connection conn=DBTools.getConnection();                                              //  老师写的一对多 是根据学生找订单 查询位置自然hi是 根据学生的sid来找 及 where sid=s.sid=?才可以
		PreparedStatement ps=conn.prepareStatement(sql);                                      //  order没有加着重  所i一写sql语句环视在 Nevicat里写把 有提示
		ps.setInt(1, id);
		ResultSet rs=ps.executeQuery();
		Order order =null;
		Student student =null;
		while(rs.next()) {
			order=new Order();
			student =new Student();
			order.setCode(rs.getString("code"));
			order.setCreateTime(rs.getTimestamp("createTime"));
			order.setOid(rs.getInt("oid"));
			order.setPrice(rs.getDouble("price"));
			
			student.setPassword(rs.getString("password"));
			student.setSid(rs.getInt("sid"));
			student.setStuName(rs.getString("stuName"));
			order.setStudent(student);
			
			
			
		}
		return order;
		
	
		
}
}
  1. 测试类
package www.oracle.test;

import org.junit.Test;

import www.oracle.dao.OrderDao;
import www.oracle.daoImpl.OrderDaoImpl;
import www.oracle.vo.Order;
import www.oracle.vo.Student;

public class TestGetStudentByOrder {
	OrderDao orderDao =new OrderDaoImpl();
	
	//一对多
	/*1. 根据订单找学生 是变相的 一对一  因为一个订单只能属于一个人
	 * 2. 根据学生找订单  就是一对多   因为一个人可有多个订单  得到订单要返回一个集合
	 * 
	 * */
	// 1. 变相 一对一
	@Test
	public void testGetStudentByOrder() throws Exception {
		Order order=orderDao.getStudentByOrder(5);
		Student s=order.getStudent();
		System.out.println(s);
	}
	//2. 一对多
	@Test
	public void testGetOrderByStudent() {
		
	}

}

一对多

难点 :StudentDaoImpl实现类的设计
实现类中要设置返回的类型Student 并写赋值代码
一查多 一中的映射是一个集合 用于存储多个从表实体

  1. SQL 语言的设计
    SQL:
    select * from student s
    inner join order o
    on s.sid=o.sid
    where s.sid=?
  2. 创造容器承接映射对象
    List orders =new ArrayList<>();
  3. ResultSet rs=ps.ExecuteQuery();
    Student studnet=null;
    Order order=null;
    while(rs.next()){
    student =new Student();
    order =new Order();
    student.set… ;
    student.set…;
    order.set…(rs.getString(" "));
    orders.add(order);
    student.setOrders(order);------------------------------ 重要

}

  1. 实体表代码
package www.oracle.vo;

import java.util.List;

public class Student {
	private Integer sid;
	private String stuName;
	private String password;
	private List<Order> orders;
	
	public List<Order> getOrders() { // 映射多个从表并存储用于
		return orders;
	}
	
	public void setOrders(List<Order> orders) {// 从表的访问器只有 set 没有get  我们得到结果只能读取集合
		this.orders = orders;
	}

	public Integer getSid() {
		return sid;
	}
	public void setSid(Integer sid) {
		this.sid = sid;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "Student [sid=" + sid + ", stuName=" + stuName + ", password=" + password + "]";
	}
	
	
	

}

order的实体

package www.oracle.vo;

import java.sql.Timestamp;

public class Order {
	private Integer oid;
	private String code;
	private Double price;
	private Timestamp createTime;
	private Student student;
	
	public Student getStudent() {
		return student;
	}
	public void setStudent(Student student) {
		this.student = student;
	}
	public Integer getOid() {
		return oid;
	}
	public void setOid(Integer oid) {
		this.oid = oid;
	}
	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	public Double getPrice() {
		return price;
	}
	public void setPrice(Double price) {
		this.price = price;
	}
	public Timestamp getCreateTime() {
		return createTime;
	}
	public void setCreateTime(Timestamp createTime) {
		this.createTime = createTime;
	}
	@Override
	public String toString() {
		return "Order [oid=" + oid + ", code=" + code + ", price=" + price + ", createTime=" + createTime + "]";
	}
	
	
	

}

接口

package www.oracle.dao;

import www.oracle.vo.Student;

public interface StudentDao {
	// 一对多  根据单表找多表并返回一个多表的集合  及映射在主表中的是一个存放多表的集合  通过返回这个主表的对象 在通过构造器去访问多表
		public Student getOrderByStudent(int id) throws Exception;

}

实现类

package www.oracle.daoImpl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import www.oracle.dao.StudentDao;
import www.oracle.util.DBTools;
import www.oracle.vo.Order;
import www.oracle.vo.Student;

public class StudentDaoImpl implements StudentDao{
	List<Order> orders =new ArrayList<>(); 

	@Override
	public Student getOrderByStudent(int id) throws Exception {
		// TODO Auto-generated method stub
		String sql="select * from student s inner join `order` o on s.sid=o.sid where o.sid=?";
		Connection conn=DBTools.getConnection();
		PreparedStatement ps= conn.prepareStatement(sql);
		ps.setInt(1, id);
		ResultSet rs=ps.executeQuery();
		Student student =null;
		Order order=null;
		while(rs.next()) {
			student=new Student(); //----------------------------------------------重要--------------------------------------
			student.setSid(rs.getInt("sid"));   //  rs.所获取的是表中查询到的数据   Student类型从 student表中获取 及 sid      Order类型从 Order表中查询获取 及 oid
			student.setPassword(rs.getString("password"));//-----------------------------------------------------------------------------------------
			student.setStuName(rs.getString("stuName"));
			order =new Order();
			order.setOid(rs.getInt("oid"));
			order.setCode(rs.getString("code"));
			order.setCreateTime(rs.getTimestamp("createTime"));
			order.setPrice(rs.getDouble("price"));
			orders.add(order);
			student.setOrders(orders);
			
		}
		return student;
	}

	
	

}

测试类

package www.oracle.test;

import java.util.List;

import org.junit.Test;

import www.oracle.dao.StudentDao;
import www.oracle.daoImpl.StudentDaoImpl;
import www.oracle.vo.Order;
import www.oracle.vo.Student;

public class TestGetOrderByStudent {
	StudentDao studentDao =new StudentDaoImpl();
	@Test
	public void testGetOrderByStudent() throws Exception {
		Student s=studentDao.getOrderByStudent(1);
		List<Order> list=s.getOrders();
		for(Order li_ :list) {
			System.out.println(li_);
		}
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值