PreparedStatement预编译查询接口
PreparedStatement是Statement接口的扩展
提供预编译功能,提高数据库访问效率
支持使用占位符设置SQL语句参数
此接口对象由Connection调用相关方法创建
PreparedStatement设置参数
void setXXX(int index,Object value);
String sql = “insert into emp values(?,?,?,?,?)”;
ps.setString(1,”东方不败”);
ps.setString(2,”黑木崖”);
ps.setInt(3,age);
ps.setInt(4,13578672660);
ps.setString(5,”dfbb@163.com”);
处理数据查询结果
使用数据库连接池组件
使用PreparedStatement优化SQL操作
分页的意义
由于在实际生产环境中,企业数据量比较庞大,在查询过程中符合查询条件的记录行比较多,全部加载到内存比较耗时,效率低下,内存容易溢出。分页查询是必要的,在页面显示时有利于页面的美观。
SQL语句实现分页
不同的数据库系统实现分页的SQL语句是不同的
Oracle通常使用rownum、rowid结合联合及子查询实现分页
Mysql使用关键字limit界定符实现分页查询功能实现
分页数据的返回
符合查询条件的记录行结果集
符合查询条件的记录行总数量
总页数
当前页码
客户端传入的分页参数
当前页码数,第几页
每页显示行数量
分页代码实现
public Map findSalary Paging(int pageNum,int pageSize){
/* 计算符合查询条件的总记录行数rowCount */
/* 计算分页总数pageSum */
/* 当前页记录行结果集rows */
/* 返回客户端需要的数据(rowCount,pageSum,rows) */
}
/*在SubjectDao中定义方法实现添加新学科的功能; 在ScoreDao 中定义方法实现添加学生成绩; 在相应的XXXDao 数据访问组件中添加相应方法完成以下功能需求: 4 根据给定的学科名称获取此属于此学科的所有及格成绩,并显示成绩的谁(学生姓名)的,及此学生属于哪个班级(显示班级名称); 任务1 分页查询功能 1 分页查询显示所有学科的学生成绩信息,包括学科名称,学生姓名,学号,分数,考试日期,是否及格; 2 分页查询显示所有某学科的所有学生成绩信息,包括学科名称,学生姓名,学号,分数,考试日期,是否及格; 3 分页查询显示某个班级的某个学科的所有成绩,包括班级名称,学科名称,学生姓名,分数,考试日期; 任务2 数据统计 4 分别统计不同专业下的所有学生人数,要求显示专业代码,专业名称,人数; 5 按照学生分组分别统计此学生的某个学科成绩的总分,平均分,要求显示学生ID,学生姓名; 6 实现将给定的的两个班级和学科名称汇总显示此两个班级的此学科总分和平飓风。 */ package com.xzit.platform.edu.dao; import com.xzit.platform.edu.pojo.Score; import com.xzit.util.DataSourceManager; import oracle.jdbc.OracleTypes; import java.sql.*; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; public class ScoreDao { /** *4 根据给定的学科名称获取此属于此学科的所有及格成绩, * 并显示成绩的谁(学生姓名)的,及此学生属于哪个班级(显示班级名称); * @param subjectName 要查询的学科名字 * @return */ public List<Map<String,Object>> queryScoresBySubject(String subjectName){ List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); String sql = "select stu.name,cla.name,sub.name,sco.scores " + "from students stu inner join score sco on stu.id = sco.stuid " + "inner join subject sub on sco.subid = sub.id " + "inner join classinfo cla on cla.id = stu.cid " + "where sub.name = '"+subjectName+"' " + "and sco.scores > 60"; Connection conn = DataSourceManager.getConnection(); //获取连接 PreparedStatement ps = null; //获取PreparedStatement接口对象 ResultSet set = null; try { ps = conn.prepareStatement(sql); set = ps.executeQuery(); //查询返回ResultSet结果集对象 /* 处理结果集,封装结果集中的Java对象 */ while(set.next()){ Map<String,Object> map = new HashMap<String,Object>(); //每行记录封装为Map对象 map.put("stuName",set.getString(1)); map.put("claName",set.getString(2)); map.put("subName",set.getString(3)); map.put("scoName",set.getString(4)); list.add(map);//将Map对象添加到List集合中 } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set); DataSourceManager.close(ps); DataSourceManager.close(conn); } return list;//返回封装Map对象的List接口对象 } /** * 1 分页查询显示所有学科的学生成绩信息,包括学科名称,学生姓名,学号,分数,考试日期,是否及格; * @param pageNum * @param pageSize * @return */ public Map<String,Object> queryAllSubjectScore(int pageNum,int pageSize){ Map<String,Object> map = new HashMap<>(); Connection conn = DataSourceManager.getConnection(); //获取连接 PreparedStatement ps2 = null; //执行查询下统计条目数 PreparedStatement ps3 = null; //执行查询结果 ResultSet set2 = null; //封装统计条目的结果集 ResultSet set3 = null; //封装统计查询结果集 int rowCount = 0;//总记录条目数 int pageSum = 0;//最后分页数量 /* 统计符合查询条件的总记录行数 */ String rowcountSql = "select COUNT(ID) ROWCOUNT FROM score"; /* 分页查询sql */ String pagingSql = "select s4.name subjectName," + "s5.name studentName," + "s5.numbers studentNum," + "s3.scores scores," + "s3.testdate testday," + "case when s3.ispass = '1' then '及格' " + "when s3.ispass = '0' then '不及格' end " + "from (select rownum rt,s2.* from score s2 where rownum <=?) s3 " + "inner join subject s4 on s3.subid = s4.id " + "inner join students s5 on s3.stuid = s5.id " + "where s3.rt >=?"; try { ps2 = conn.prepareStatement(rowcountSql); set2 = ps2.executeQuery();//执行条目统计 while(set2.next()){ rowCount = set2.getInt(1); } map.put("rowCount",rowCount); /* 统计总共分成多少页(总记录行数/pageSize) */ pageSum = countPageSum(rowCount,pageSize); map.put("pageSum",pageSum); /* 统计符合条件每页结果集 */ ps3 = conn.prepareStatement(pagingSql); ps3.setInt(1,pageSize*pageNum);//设置第一个? ps3.setInt(2,pageSize*pageNum-(pageSize-1)); set3 = ps3.executeQuery(); List<Map<String,Object>> rows = new ArrayList<>(); while (set3.next()){ Map<String,Object> rowMap = new HashMap<>(); rowMap.put("subjectName",set3.getString(1)); rowMap.put("studentName",set3.getString(2)); rowMap.put("studentNum",set3.getString(3)); rowMap.put("scores",set3.getString(4)); rowMap.put("testday",set3.getDate(5)); rows.add(rowMap); } map.put("rows",rows);//添加到查询结果集List map中 } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set3); DataSourceManager.close(set2); DataSourceManager.close(ps3); DataSourceManager.close(ps2); DataSourceManager.close(conn); } return map; } /** * 计算总共分成多少页 * @param rowCount * @param pageSize * @return */ public int countPageSum(int rowCount,int pageSize){ /** * 三目运算符,如果总行数rowCount除以一页要显示的行数pageSize余0, * 意味着一页中可以显示pageSize这么多行,例总行数10行,除以要显示5行余0,意味着可以分成2页 * 否则显示rowCount/pageSize+1行,例总行数11行,除以要显示5行等于2.2,+1等于3.2,约等于3页 */ return rowCount%pageSize==0 ? rowCount/pageSize : rowCount/pageSize+1; } /** * 2 分页查询显示所有某学科的所有学生成绩信息,包括学科名称,学生姓名,学号,分数,考试日期,是否及格; * @param pageNum * @param pageSize * @return */ public Map<String,Object> queryScoreBySubName(int pageNum,int pageSize,String subjectName){ Map<String,Object> map = new HashMap<>(); Connection conn = DataSourceManager.getConnection(); //获取连接 PreparedStatement ps2 = null; //执行查询下统计条目数 PreparedStatement ps3 = null; //执行查询结果 ResultSet set2 = null; //封装统计条目的结果集 ResultSet set3 = null; //封装统计查询结果集 int rowCount = 0;//总记录条目数 int pageSum = 0;//最后分页数量 /* 统计符合查询条件的总记录行数 */ String rowcountSql = "select COUNT(s1.ID) ROWCOUNT FROM score s1 " + "inner join subject s2 on s1.subid = s2.id " + "where s2.name = '"+subjectName+"'"; /* 分页查询sql */ String pagingSql = "select s4.name subjectName," + "s5.name studentName," + "s5.numbers studentNum," + "s3.scores scores," + "s3.testdate testday," + "case when s3.ispass = '1' then '及格' " + "when s3.ispass = '0' then '不及格' end " + "from (select rownum rt,s2.* from score s2 where rownum <=?) s3 " + "inner join subject s4 on s3.subid = s4.id " + "inner join students s5 on s3.stuid = s5.id " + "where s3.rt >=? and s4.name = ?"; try { ps2 = conn.prepareStatement(rowcountSql); set2 = ps2.executeQuery();//执行条目统计 while(set2.next()){ rowCount = set2.getInt(1); } map.put("rowCount",rowCount); /* 统计总共分成多少页(总记录行数/pageSize) */ pageSum = countPageSum(rowCount,pageSize); map.put("pageSum",pageSum); /* 统计符合条件每页结果集 */ ps3 = conn.prepareStatement(pagingSql); ps3.setInt(1,pageSize*pageNum);//设置第一个? ps3.setInt(2,pageSize*pageNum-(pageSize-1)); ps3.setString(3,subjectName); set3 = ps3.executeQuery(); List<Map<String,Object>> rows = new ArrayList<>(); while (set3.next()){ Map<String,Object> rowMap = new HashMap<>(); rowMap.put("subjectName",set3.getString(1)); rowMap.put("studentName",set3.getString(2)); rowMap.put("studentNum",set3.getString(3)); rowMap.put("scores",set3.getString(4)); rowMap.put("testday",set3.getDate(5)); rows.add(rowMap); } map.put("rows",rows);//添加到查询结果集List map中 } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set3); DataSourceManager.close(set2); DataSourceManager.close(ps3); DataSourceManager.close(ps2); DataSourceManager.close(conn); } return map; } /** * 3 分页查询显示某个班级的某个学科的所有成绩,包括班级名称,学科名称,学生姓名,分数,考试日期; * @param pageNum * @param pageSize * @return */ public Map<String,Object> queryScoreByClassInfo(int pageNum,int pageSize,String className){ Map<String,Object> map = new HashMap<>(); Connection conn = DataSourceManager.getConnection(); //获取连接 PreparedStatement ps2 = null; //执行查询下统计条目数 PreparedStatement ps3 = null; //执行查询结果 ResultSet set2 = null; //封装统计条目的结果集 ResultSet set3 = null; //封装统计查询结果集 int rowCount = 0;//总记录条目数 int pageSum = 0;//最后分页数量 /* 统计符合查询条件的总记录行数 */ String rowcountSql = "select COUNT(s1.ID) ROWCOUNT FROM score s1 " + "inner join students s5 on s1.stuid = s5.id " + "inner join subject s2 on s1.subid = s2.id " + "inner join ClassInfo c1 on s5.cid = c1.id " + "where c1.name = '"+className+"'"; /* 分页查询sql */ String pagingSql = "select c1.name className," + "s4.name subjectName," + "s5.name studentName," + "s5.numbers studentNum," + "s3.scores scores," + "s3.testdate testday," + "case when s3.ispass = '1' then '及格' " + "when s3.ispass = '0' then '不及格' end " + "from (select rownum rt,s2.* from score s2 where rownum <=?) s3 " + "inner join students s5 on s3.stuid = s5.id " + "inner join subject s4 on s3.subid = s4.id " + "inner join ClassInfo c1 on s5.cid = c1.id " + "where s3.rt >=? and c1.name = ?"; try { ps2 = conn.prepareStatement(rowcountSql); set2 = ps2.executeQuery();//执行条目统计 while(set2.next()){ rowCount = set2.getInt(1); } map.put("rowCount",rowCount); /* 统计总共分成多少页(总记录行数/pageSize) */ pageSum = countPageSum(rowCount,pageSize); map.put("pageSum",pageSum); /* 统计符合条件每页结果集 */ ps3 = conn.prepareStatement(pagingSql); ps3.setInt(1,pageSize*pageNum);//设置第一个? ps3.setInt(2,pageSize*pageNum-(pageSize-1)); ps3.setString(3,className); set3 = ps3.executeQuery(); List<Map<String,Object>> rows = new ArrayList<>(); while (set3.next()){ Map<String,Object> rowMap = new HashMap<>(); rowMap.put("className",set3.getString(1)); rowMap.put("subjectName",set3.getString(2)); rowMap.put("studentName",set3.getString(3)); rowMap.put("studentNum",set3.getString(4)); rowMap.put("scores",set3.getString(5)); rowMap.put("testday",set3.getDate(6)); rows.add(rowMap); } map.put("rows",rows);//添加到查询结果集List map中 } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set3); DataSourceManager.close(set2); DataSourceManager.close(ps3); DataSourceManager.close(ps2); DataSourceManager.close(conn); } return map; } /** * 4 分别统计不同专业下的所有学生人数,要求显示专业代码,专业名称,人数; * @return */ public List<Map<String,Object>> sumStudentsByMajor(){ List<Map<String,Object>> list = new ArrayList<>(); String sql = "select m.id,m.name,sum(s.id) " + "from major m inner join classinfo c on m.id = c.mid " + "inner join students s on c.id = s.cid " + "group by m.id,m.name "; Connection conn = DataSourceManager.getConnection();//获取数据库连接 PreparedStatement ps = null; //获取PeparedStatement接口对象 ResultSet set = null; //创建一个ResultSet结果集 try { ps = conn.prepareStatement(sql); set = ps.executeQuery(); while (set.next()){ Map<String,Object> map = new HashMap<>();//每一行封装一个map对象 map.put("majorId",set.getString(1)); map.put("majorName",set.getString(2)); map.put("sumId",set.getString(3)); list.add(map); //将Map对象添加到List集合中 } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set); DataSourceManager.close(ps); DataSourceManager.close(conn); } return list;//返回封装Map对象的List接口对 } /** * 5 按照学生分组分别统计此学生的某个学科成绩的总分,平均分,要求显示学生ID,学生姓名; * @param subjectName * @return */ public List<Map<String,Object>> sumScoreBySubject(String subjectName){ List<Map<String,Object>> list = new ArrayList<>(); String sql = "select s3.id,s3.name,s2.name,sum(s1.scores),avg(s1.scores) " + "from score s1 inner join subject s2 on s1.subid = s2.id " + "inner join students s3 on s1.stuid = s3.id " + "and s2.name = '"+subjectName+"'" + "group by s3.id,s3.name,s2.name "; Connection conn = DataSourceManager.getConnection();//获取数据库连接 PreparedStatement ps = null; //获取PeparedStatement接口对象 ResultSet set = null; //创建一个ResultSet结果集 try { ps = conn.prepareStatement(sql); set = ps.executeQuery(); while (set.next()){ Map<String,Object> map = new HashMap<>();//每一行封装一个map对象 map.put("stuId",set.getString(1)); map.put("stuName",set.getString(2)); map.put("subName",set.getString(3)); map.put("sumScore",set.getString(4)); map.put("avgScore",set.getString(5)); list.add(map);//将Map对象添加到List集合中 } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set); DataSourceManager.close(ps); DataSourceManager.close(conn); } return list; } /** * 6 实现将给定的的两个班级和学科名称汇总显示此两个班级的此学科总分和平均分。 * @param classname1 * @param classname2 * @param subjectName * @return */ public List<Map<String,Object>> sumScoreByClassInfo(String classname1,String classname2,String subjectName){ List<Map<String,Object>> list = new ArrayList<>(); String sql = "select c.name," + "s3.name," + "sum(s2.scores)," + "avg(s2.scores) " + "from classinfo c inner join students s1 on c.id = s1.cid " + "inner join score s2 on s1.id = s2.stuid " + "inner join subject s3 on s3.id = s2.subid " + "and c.name = '"+classname1+"' " + "and s3.name = '"+subjectName+"' " + "or c.name = '"+classname2+"' " + "and s3.name = '"+subjectName+"' " + "group by c.name,s3.name"; Connection conn = DataSourceManager.getConnection();//获取数据库连接 PreparedStatement ps = null; //获取PeparedStatement接口对象 ResultSet set = null; //创建一个ResultSet结果集 try { ps = conn.prepareStatement(sql); set = ps.executeQuery(); while (set.next()){ Map<String,Object> map = new HashMap<>();//每一行封装一个map对象 map.put("className",set.getString(1)); map.put("subName",set.getString(2)); map.put("sumScore",set.getString(3)); map.put("avgScore",set.getString(4)); list.add(map);//将Map对象添加到List集合中 } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(set); DataSourceManager.close(ps); DataSourceManager.close(conn); } return list; } /** * 1 在数据库中定义一个存储过程,完成给定班级名称和学号及学科, * 获取此学生此学科成绩所有信息,在应用程序中定义相关方法完成调用此存储过程显示成绩信息。 * @param stuNumbers * @param subjectName * @return */ public List<Map<String,Object>> callProcedure3(String stuNumbers,String subjectName){ List<Map<String,Object>> list = new ArrayList<>(); String procName = "{call pro_querySubject(:stuNumbers,:subjectName,:datas)}"; Connection conn = DataSourceManager.getConnection();//获取数据库连接 CallableStatement call = null; ResultSet rs = null; try { call = conn.prepareCall(procName);//创建CallableStatement对象 /* 注册oralce游标类型,此类型可以封装查询结果 */ call.registerOutParameter("stuNumbers",Types.VARCHAR); call.setString("stuNumbers",stuNumbers); call.registerOutParameter("subjectName",Types.VARCHAR); call.setString("subjectName",subjectName); call.registerOutParameter("datas", oracle.jdbc.OracleTypes.CURSOR); call.execute(); rs = (ResultSet) call.getObject("datas");//获取返回输出类型 while(rs.next()){//遍历结果集封装为对象 Map<String,Object> map = new HashMap<>(); map.put("stuNumber",rs.getString(1)); map.put("className",rs.getString(2)); map.put("subName",rs.getString(3)); map.put("scores",rs.getString(4)); list.add(map); } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(rs); DataSourceManager.close(call); DataSourceManager.close(conn); } return list; } }
package com.xzit.platform.edu.test; import com.xzit.platform.edu.dao.ScoreDao; import com.xzit.platform.edu.dao.SubjectDao; import com.xzit.platform.edu.pojo.Students; import com.xzit.platform.edu.pojo.Subject; import java.util.List; import java.util.Map; public class TestQuery { public static void main(String[] args) { /* 1 根据给定的院系名称获取属于此院系的所有专业信息 */ List<Subject> subs = new SubjectDao().querySubjectList(); System.out.println("ID编号 学科编号 学科名称 是否必修 状态 设置日期 备注"); for (Subject sub:subs){ System.out.println(sub.getId()+" "+sub.getNumbers()+" "+ sub.getName()+" "+sub.getObligatory()+" "+sub.getStatus() +" "+sub.getCreateDate()+" "+sub.getDescription()); } System.out.println("------------------------------------------------------"); /* 3 根据给定的班级名称获取此班级下的所有性别为男的学生信息,并按照生日排序(倒序),性别为1以”男”作为显示; */ List<Students> stus = new SubjectDao().queryStudentsByClassInfo("信管2班"); for(Students stu:stus){ System.out.println(stu.getId()+" "+stu.getNumbers()+" "+ stu.getName()+" "+stu.getGender()+" "+ stu.getBirth()+" "+stu.getPhone()+" "+ stu.getDaid()+" "+stu.getCid()+" "+ stu.getApartment()+" "+stu.getDescripte()); } System.out.println("------------------------------------------------------"); /* 4 分别统计不同专业下的所有学生人数,要求显示专业代码,专业名称,人数; */ List<Map<String,Object>> list = new ScoreDao().sumStudentsByMajor(); System.out.println("专业代码 专业名称 学生人数"); for (Map<String,Object> map :list){ System.out.println( map.get("majorId")+" "+ map.get("majorName")+" "+ map.get("sumId") ); } System.out.println("------------------------------------------------------"); /* 5 按照学生分组分别统计此学生的某个学科成绩的总分,平均分,要求显示学生ID,学生姓名; */ List<Map<String,Object>> list2 = new ScoreDao().sumScoreBySubject("流体力学"); System.out.println("学生id 学生姓名 科目名称 成绩总和 平均分"); for (Map<String,Object> map2:list2){ System.out.println(map2.get("stuId")+" "+ map2.get("stuName")+" "+ map2.get("subName")+" "+ map2.get("sumScore")+" "+ map2.get("avgScore") ); } System.out.println("------------------------------------------------------"); /* 6 实现将给定的的两个班级和学科名称汇总显示此两个班级的此学科总分和平均分 */ List<Map<String,Object>> list3 = new ScoreDao().sumScoreByClassInfo("信管2班","软工1班","Java开发"); System.out.println("班级名称 学科名称 成绩总和 成绩总和 平均分"); for (Map<String,Object> map3:list3){ System.out.println(map3.get("className")+" "+ map3.get("subName")+" "+ map3.get("sumScore")+" "+ map3.get("avgScore") ); } System.out.println("------------------------------------------------------"); List<Map<String,Object>> list4 = new ScoreDao().callProcedure3("流体力学","110380"); for(Map<String,Object> map:list4){ System.out.println(map.get("stuNumber") +" "+map.get("className") +" "+map.get("subName") +" "+map.get("scores") ); } } }