JDBC多表联查
在单一表进行查询时,只需要对表中的单个字段进行解析即可;例如下面代码:
@Override
public List<ClassBean> selectAllDao() {
List list = new ArrayList();
try {
String sql = "select * from class";
rs = select(sql);
while(rs.next()) {
ClassBean cb = new ClassBean();
cb.setClassId(rs.getInt("classid"));
cb.setClassName(rs.getString("classname"));
list.add(cb);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
DaoUtil.closeResource(conn, statement, rs);
}
return list;
}
在进行多表联查时会遇到第一个问题就是在实体类中不存在从表的字段,紧接着第二个问题在就是主表与从表的对应关系是一对一还是一对多关系。
以学生和班级表为例:从图中可以看出表对应关系
两个表的结构如下:
创建两个实体类:
student的实体类,加入外部属性,也就是引入class的属性,以为学生和班级是一对一的关系,因此只需要一个班级对象即可:
public class Student {
private int sid;
private String sname;
private Date birthday;
private String ssex;
private int classId;
//外部属性
private Banji bj;
//get、set、构造器、toString方法省略
}
Banji表(class是Java关键字,所以用拼音)分析可知,一个班级里有多个学生,因此需要引入一个集合外部属性,用来存储班级中的多个学生:
public class Banji {
private int classId;
private String className;
//外部属性
private List<Student> stu;
//get、set、构造器、toString方法省略
}
在这里将部分的代码进行了封装,形成了两个类:
DaoUtil工具类:
package com.li.dao;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DaoUtil {
private static DataSource ds = null;
static {
try {
FileInputStream stream = new FileInputStream("./src/druid.properties");
Properties pro = new Properties();
pro.load(stream);
//创建连接
ds = DruidDataSourceFactory.createDataSource(pro);
}catch(Exception e) {
e.printStackTrace();
}
}
//创建连接对象方法
public static Connection getConn() {
Connection conn = null;
try {
conn = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
//关闭资源操作
public static void closeResource(Connection conn,PreparedStatement prestatm, ResultSet rs) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(prestatm != null) {
try {
prestatm.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
BaseDao工具类:
package com.li.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class BaseDao {
protected Connection conn;
protected PreparedStatement prestatm;
protected ResultSet rs;
protected ResultSet query(String sql, Object ... arge) {
ResultSet rs = null;
try {
conn = DaoUtil.getConn();
prestatm = conn.prepareStatement(sql);
if(arge != null) {
for(int i = 0; i< arge.length; i++) {
prestatm.setObject(i+1, arge[i]);
}
}
rs = prestatm.executeQuery();
} catch (Exception e) {
e.printStackTrace();
}
return rs;
}
}
学生的实现类(接口省略):
package com.li.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.li.bean.Banji;
import com.li.bean.Student;
import com.li.dao.BaseDao;
import com.li.dao.DaoUtil;
import com.li.dao.IStudentDao;
public class StudentDaoImpl extends BaseDao implements IStudentDao{
@Override
public List<Student> findAllStudent() {
List<Student> list = new ArrayList();
try {
String sql = "select * from student left join class on student.classid = class.classid";
rs = query(sql);
while (rs.next()) {
Student stu = new Student();
Banji bj = new Banji();
// 学生的数据
stu.setBirthday(rs.getDate("birthday"));
stu.setClassId(rs.getInt("classid"));
stu.setSid(rs.getInt("sid"));
stu.setSname(rs.getString("sname"));
stu.setSsex(rs.getString("ssex"));
//给班级属性赋值
bj.setClassId(rs.getInt("classid"));
bj.setClassName(rs.getString("classname"));
//将班级对象赋值给班级中定义的实体类
stu.setBj(bj);
list.add(stu);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
DaoUtil.closeResource(conn, prestatm, rs);
}
return list;
}
}
班级的集合中存放班级编号等信息,班级编号的集合中又存放学生,就是集合中套集合:
Banji实现类(接口省略):
package com.li.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.li.bean.Banji;
import com.li.bean.Student;
import com.li.dao.BaseDao;
import com.li.dao.DaoUtil;
import com.li.dao.IBanjiDao;
public class BanjiDaoImpl extends BaseDao implements IBanjiDao{
@Override
public List<Banji> findAllBanji() {
List<Banji> blist = new ArrayList();
String sql = "select * from class left join student on class.classid = student.classid";
rs = query(sql);
try {
while(rs.next()) {
boolean falg = false;
int index = -1;
for(int i = 0; i <blist.size(); i++) {
//判断班级集合中是否存在某字段的班级编号
if(rs.getInt("classid") == blist.get(i).getClassId()) {
falg =true;
index = i;
break;
}
}
//已经存在班级集合
if(falg) {
Student stu = new Student();
stu.setBirthday(rs.getDate("birthday"));
stu.setClassId(rs.getInt("classid"));
stu.setSid(rs.getInt("sid"));
stu.setSname(rs.getString("sname"));
stu.setSsex(rs.getString("ssex"));
Banji banji = blist.get(index);
banji.getStu().add(stu);
}
//不存在班级集合
else {
//新建班级集合并放入
List<Student> slist = new ArrayList();
Banji bj = new Banji();
bj.setClassId(rs.getInt("classId"));
bj.setClassName(rs.getString("classname"));
bj.setStu(slist);
//新建学生类放入集合中
Student stu = new Student();
stu.setBirthday(rs.getDate("birthday"));
stu.setClassId(rs.getInt("classid"));
stu.setSid(rs.getInt("sid"));
stu.setSname(rs.getString("sname"));
stu.setSsex(rs.getString("ssex"));
slist.add(stu);
blist.add(bj);
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
DaoUtil.closeResource(conn, prestatm, rs);
}
return blist;
}
}
测试类:
public static void main(String[] args) {
IBanjiDao bjd = new BanjiDaoImpl();
List<Banji> list = bjd.findAllBanji();
IStudentDao sdi = new StudentDaoImpl();
List<Student> list = sdi.findAllStudent();
list.forEach(System.out::println);
}