JDBC(一)(2)+https://developer.aliyun.com/article/1556652
3.5 实操
代码结构:
util/JDBCUtils.java
package com.atguigu3.util; /** * * @Description 操作数据库的工具类 * @author shkstart Email:shkstart@126.com * @version * @date 上午9:10:02 * */ public class JDBCUtils { /** * * @Description 获取数据库的连接 * @author shkstart * @date 上午9:11:23 * @return * @throws Exception */ public static Connection getConnection() throws Exception { // 1.读取配置文件中的4个基本信息 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driverClass = pros.getProperty("driverClass"); // 2.加载驱动 Class.forName(driverClass); // 3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); return conn; } /** * * @Description 关闭连接和Statement的操作 * @author shkstart * @date 上午9:12:40 * @param conn * @param ps */ public static void closeResource(Connection conn,Statement ps){ try { if(ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } try { if(conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } /** * * @Description 关闭资源操作 * @author shkstart * @date 上午10:21:15 * @param conn * @param ps * @param rs */ public static void closeResource(Connection conn,Statement ps,ResultSet rs){ try { if(ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } try { if(conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } try { if(rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } } }
bean/Customer.java
package com.atguigu3.bean; import java.sql.Date; /* * ORM编程思想 (object relational mapping) * 一个数据表对应一个java类 * 表中的一条记录对应java类的一个对象 * 表中的一个字段对应java类的一个属性 * */ public class Customer { private int id; private String name; private String email; private Date birth; //这里有参构造、无参构造、get、set、toString方法省略了。。。 }
bean/Order.java
package com.atguigu3.bean; import java.sql.Date; public class Order { private int orderId; private String orderName; private Date orderDate; //这里有参构造、无参构造、get、set、toString方法省略了。。。 }
CustomerForQuery.java
package com.atguigu3.preparedstatement.crud; import com.atguigu3.bean.Customer; import com.atguigu3.util.JDBCUtils; /** * * @Description 针对于Customers表的查询操作 * @author shkstart Email:shkstart@126.com * @version * @date 上午10:04:55 * */ public class CustomerForQuery { @Test public void testQueryForCustomers(){ String sql = "select id,name,birth,email from customers where id = ?"; Customer customer = queryForCustomers(sql, 13); System.out.println(customer); sql = "select name,email from customers where name = ?"; Customer customer1 = queryForCustomers(sql,"周杰伦"); System.out.println(customer1); } /** * * @Description 针对于customers表的通用的查询操作 * @author shkstart * @throws Exception * @date 上午10:23:40 */ public Customer queryForCustomers(String sql,Object...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); ps = conn.prepareStatement(sql); for(int i = 0;i < args.length;i++){ ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); //获取结果集的元数据 :ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData(); //通过ResultSetMetaData获取结果集中的列数 int columnCount = rsmd.getColumnCount(); if(rs.next()){ Customer cust = new Customer(); //处理结果集一行数据中的每一个列 for(int i = 0;i <columnCount;i++){ //获取列值 Object columValue = rs.getObject(i + 1); //获取每个列的列名 // String columnName = rsmd.getColumnName(i + 1); String columnLabel = rsmd.getColumnLabel(i + 1); //给cust对象指定的columnName属性,赋值为columValue:通过反射 Field field = Customer.class.getDeclaredField(columnLabel); field.setAccessible(true); field.set(cust, columValue); } return cust; } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtils.closeResource(conn, ps, rs); } return null; } @Test public void testQuery1() { Connection conn = null; PreparedStatement ps = null; ResultSet resultSet = null; try { conn = JDBCUtils.getConnection(); String sql = "select id,name,email,birth from customers where id = ?"; ps = conn.prepareStatement(sql); ps.setObject(1, 1); //执行,并返回结果集 resultSet = ps.executeQuery(); //处理结果集 if(resultSet.next()){//next():判断结果集的下一条是否有数据,如果有数据返回true,并指针下移;如果返回false,指针不会下移。 //获取当前这条数据的各个字段值 int id = resultSet.getInt(1); String name = resultSet.getString(2); String email = resultSet.getString(3); Date birth = resultSet.getDate(4); //方式一: // System.out.println("id = " + id + ",name = " + name + ",email = " + email + ",birth = " + birth); //方式二: // Object[] data = new Object[]{id,name,email,birth}; //方式三:将数据封装为一个对象(推荐) Customer customer = new Customer(id, name, email, birth); System.out.println(customer); } } catch (Exception e) { e.printStackTrace(); }finally{ //关闭资源 JDBCUtils.closeResource(conn, ps, resultSet); } } }
OrderForQuery.java
package com.atguigu3.preparedstatement.crud; import com.atguigu3.bean.Order; import com.atguigu3.util.JDBCUtils; /** * * @Description 针对于Order表的通用的查询操作 * @author shkstart Email:shkstart@126.com * @version * @date 上午10:43:58 * */ public class OrderForQuery { /* * 针对于表的字段名与类的属性名不相同的情况: * 1. 必须声明sql时,使用类的属性名来命名字段的别名 * 2. 使用ResultSetMetaData时,需要使用getColumnLabel()来替换getColumnName(), * 获取列的别名。 * 说明:如果sql中没有给字段其别名,getColumnLabel()获取的就是列名 * * */ @Test public void testOrderForQuery(){ String sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id = ?"; Order order = orderForQuery(sql,1); System.out.println(order); } /** * * @Description 通用的针对于order表的查询操作 * @author shkstart * @date 上午10:51:12 * @return * @throws Exception */ public Order orderForQuery(String sql,Object...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); ps = conn.prepareStatement(sql); for(int i = 0;i < args.length;i++){ ps.setObject(i + 1, args[i]); } //执行,获取结果集 rs = ps.executeQuery(); //获取结果集的元数据 ResultSetMetaData rsmd = rs.getMetaData(); //获取列数 int columnCount = rsmd.getColumnCount(); if(rs.next()){ Order order = new Order(); for(int i = 0;i < columnCount;i++){ //获取每个列的列值:通过ResultSet Object columnValue = rs.getObject(i + 1); //通过ResultSetMetaData //获取列的列名:getColumnName() --不推荐使用 //获取列的别名:getColumnLabel() // String columnName = rsmd.getColumnName(i + 1); String columnLabel = rsmd.getColumnLabel(i + 1); //通过反射,将对象指定名columnName的属性赋值为指定的值columnValue Field field = Order.class.getDeclaredField(columnLabel); field.setAccessible(true); field.set(order, columnValue); } return order; } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtils.closeResource(conn, ps, rs); } return null; } @Test public void testQuery1(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); String sql = "select order_id,order_name,order_date from `order` where order_id = ?"; ps = conn.prepareStatement(sql); ps.setObject(1, 1); rs = ps.executeQuery(); if(rs.next()){ int id = (int) rs.getObject(1); String name = (String) rs.getObject(2); Date date = (Date) rs.getObject(3); Order order = new Order(id, name, date); System.out.println(order); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtils.closeResource(conn, ps, rs); } } }
PreparedStatementQueryTest.java
package com.atguigu3.preparedstatement.crud; import com.atguigu3.bean.Customer; import com.atguigu3.bean.Order; import com.atguigu3.util.JDBCUtils; /** * * @Description 使用PreparedStatement实现针对于不同表的通用的查询操作 * @author shkstart Email:shkstart@126.com * @version * @date 上午11:32:55 * */ public class PreparedStatementQueryTest { @Test public void testGetForList(){ String sql = "select id,name,email from customers where id < ?"; List<Customer> list = getForList(Customer.class,sql,12); list.forEach(System.out::println); String sql1 = "select order_id orderId,order_name orderName from `order`"; List<Order> orderList = getForList(Order.class, sql1); orderList.forEach(System.out::println); } public <T> List<T> getForList(Class<T> clazz,String sql, Object... args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); // 获取结果集的元数据 :ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData(); // 通过ResultSetMetaData获取结果集中的列数 int columnCount = rsmd.getColumnCount(); //创建集合对象 ArrayList<T> list = new ArrayList<T>(); while (rs.next()) { T t = clazz.newInstance(); // 处理结果集一行数据中的每一个列:给t对象指定的属性赋值 for (int i = 0; i < columnCount; i++) { // 获取列值 Object columValue = rs.getObject(i + 1); // 获取每个列的列名 // String columnName = rsmd.getColumnName(i + 1); String columnLabel = rsmd.getColumnLabel(i + 1); // 给t对象指定的columnName属性,赋值为columValue:通过反射 Field field = clazz.getDeclaredField(columnLabel); field.setAccessible(true); field.set(t, columValue); } list.add(t); } return list; } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(conn, ps, rs); } return null; } @Test public void testGetInstance(){ String sql = "select id,name,email from customers where id = ?"; Customer customer = getInstance(Customer.class,sql,12); System.out.println(customer); String sql1 = "select order_id orderId,order_name orderName from `order` where order_id = ?"; Order order = getInstance(Order.class, sql1, 1); System.out.println(order); } /** * * @Description 针对于不同的表的通用的查询操作,返回表中的一条记录 * @author shkstart * @date 上午11:42:23 * @param clazz * @param sql * @param args * @return */ public <T> T getInstance(Class<T> clazz,String sql, Object... args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); // 获取结果集的元数据 :ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData(); // 通过ResultSetMetaData获取结果集中的列数 int columnCount = rsmd.getColumnCount(); if (rs.next()) { T t = clazz.newInstance(); // 处理结果集一行数据中的每一个列 for (int i = 0; i < columnCount; i++) { // 获取列值 Object columValue = rs.getObject(i + 1); // 获取每个列的列名 // String columnName = rsmd.getColumnName(i + 1); String columnLabel = rsmd.getColumnLabel(i + 1); // 给t对象指定的columnName属性,赋值为columValue:通过反射 Field field = clazz.getDeclaredField(columnLabel); field.setAccessible(true); field.set(t, columValue); } return t; } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(conn, ps, rs); } return null; } }
PreparedStatementUpdateTest.java
package com.atguigu3.preparedstatement.crud; import com.atguigu1.connection.ConnectionTest; import com.atguigu3.util.JDBCUtils; /* * 使用PreparedStatement来替换Statement,实现对数据表的增删改操作 * * 增删改;查 * * */ public class PreparedStatementUpdateTest { @Test public void testCommonUpdate(){ // String sql = "delete from customers where id = ?"; // update(sql,3); String sql = "update `order` set order_name = ? where order_id = ?"; update(sql,"DD","2"); } //通用的增删改操作 public void update(String sql,Object ...args){//sql中占位符的个数与可变形参的长度相同! Connection conn = null; PreparedStatement ps = null; try { //1.获取数据库的连接 conn = JDBCUtils.getConnection(); //2.预编译sql语句,返回PreparedStatement的实例 ps = conn.prepareStatement(sql); //3.填充占位符 for(int i = 0;i < args.length;i++){ ps.setObject(i + 1, args[i]);//小心参数声明错误!! } //4.执行 ps.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ //5.资源的关闭 JDBCUtils.closeResource(conn, ps); } } //修改customers表的一条记录 @Test public void testUpdate(){ Connection conn = null; PreparedStatement ps = null; try { //1.获取数据库的连接 conn = JDBCUtils.getConnection(); //2.预编译sql语句,返回PreparedStatement的实例 String sql = "update customers set name = ? where id = ?"; ps = conn.prepareStatement(sql); //3.填充占位符 ps.setObject(1,"莫扎特"); ps.setObject(2, 18); //4.执行 ps.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ //5.资源的关闭 JDBCUtils.closeResource(conn, ps); } } // 向customers表中添加一条记录 @Test public void testInsert() { Connection conn = null; PreparedStatement ps = null; try { // 1.读取配置文件中的4个基本信息 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driverClass = pros.getProperty("driverClass"); // 2.加载驱动 Class.forName(driverClass); // 3.获取连接 conn = DriverManager.getConnection(url, user, password); // System.out.println(conn); //4.预编译sql语句,返回PreparedStatement的实例 String sql = "insert into customers(name,email,birth)values(?,?,?)";//?:占位符 ps = conn.prepareStatement(sql); //5.填充占位符 ps.setString(1, "哪吒"); ps.setString(2, "nezha@gmail.com"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); java.util.Date date = sdf.parse("1000-01-01"); ps.setDate(3, new Date(date.getTime())); //6.执行操作 ps.execute(); } catch (Exception e) { e.printStackTrace(); }finally{ //7.资源的关闭 try { if(ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } try { if(conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
练习
练习题1:从控制台向数据库的表customers中插入一条数据,表结构如下:
代码结构如下:
Exer1Test.java
package com.atguigu4.exer; import com.atguigu3.util.JDBCUtils; //课后练习1 public class Exer1Test { @Test public void testInsert(){ Scanner scanner = new Scanner(System.in); System.out.print("请输入用户名:"); String name = scanner.next(); System.out.print("请输入邮箱:"); String email = scanner.next(); System.out.print("请输入生日:"); String birthday = scanner.next();//'1992-09-08' String sql = "insert into customers(name,email,birth)values(?,?,?)"; int insertCount = update(sql,name,email,birthday); if(insertCount > 0){ System.out.println("添加成功"); }else{ System.out.println("添加失败"); } } // 通用的增删改操作 public int update(String sql, Object... args) {// sql中占位符的个数与可变形参的长度相同! Connection conn = null; PreparedStatement ps = null; try { // 1.获取数据库的连接 conn = JDBCUtils.getConnection(); // 2.预编译sql语句,返回PreparedStatement的实例 ps = conn.prepareStatement(sql); // 3.填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]);// 小心参数声明错误!! } // 4.执行 /* * ps.execute(): * 如果执行的是查询操作,有返回结果,则此方法返回true; * 如果执行的是增、删、改操作,没有返回结果,则此方法返回false. */ //方式一: // return ps.execute(); //方式二: return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { // 5.资源的关闭 JDBCUtils.closeResource(conn, ps); } return 0; } }
练习题2:创立数据库表 examstudent,表结构如下:
向数据表中添加如下数据:
代码实现1:插入一个新的student 信息
请输入考生的详细信息
Type:
IDCard:
ExamCard:
StudentName:
Location:
Grade:
信息录入成功!
Student.java
package com.atguigu4.exer; /* * Type: IDCard: ExamCard: StudentName: Location: Grade: */ public class Student { private int flowID;//流水号 private int type;//考试类型 private String IDCard;//身份证号 private String examCard;//准考证号 private String name;//学生姓名 private String location;//所在城市 //这里有参构造、无参构造、get、set、toString方法省略了。。。 }
Exer2Test.java
package com.atguigu4.exer; import com.atguigu3.util.JDBCUtils; //课后练习2 public class Exer2Test { // 问题1:向examstudent表中添加一条记录 /* * Type: IDCard: ExamCard: StudentName: Location: Grade: */ @Test public void testInsert(){ Scanner scanner = new Scanner(System.in); System.out.print("四级/六级:"); int type = scanner.nextInt(); System.out.print("身份证号:"); String IDCard = scanner.next(); System.out.print("准考证号:"); String examCard = scanner.next(); System.out.print("学生姓名:"); String studentName = scanner.next(); System.out.print("所在城市:"); String location = scanner.next(); System.out.print("考试成绩:"); int grade = scanner.nextInt(); String sql = "insert into examstudent(type,IDCard,examCard,studentName,location,grade)values(?,?,?,?,?,?)"; int insertCount = update(sql,type,IDCard,examCard,studentName,location,grade); if(insertCount > 0){ System.out.println("添加成功"); }else{ System.out.println("添加失败"); } } // 通用的增删改操作 public int update(String sql, Object... args) {// sql中占位符的个数与可变形参的长度相同! Connection conn = null; PreparedStatement ps = null; try { // 1.获取数据库的连接 conn = JDBCUtils.getConnection(); // 2.预编译sql语句,返回PreparedStatement的实例 ps = conn.prepareStatement(sql); // 3.填充占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]);// 小心参数声明错误!! } // 4.执行 /* * ps.execute(): * 如果执行的是查询操作,有返回结果,则此方法返回true; * 如果执行的是增、删、改操作,没有返回结果,则此方法返回false. */ // 方式一: // return ps.execute(); // 方式二: return ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { // 5.资源的关闭 JDBCUtils.closeResource(conn, ps); } return 0; } }
代码实现2:在 eclipse中建立 java 程序:输入身份证号或准考证号可以查询到学生的基本信息。结果如下:
//问题2:根据身份证号或者准考证号查询学生成绩信息 @Test public void queryWithIDCardOrExamCard(){ System.out.println("请选择您要输入的类型:"); System.out.println("a.准考证号"); System.out.println("b.身份证号"); Scanner scanner = new Scanner(System.in); String selection = scanner.next(); if("a".equalsIgnoreCase(selection)){//if(selection.equalsIgnoreCase("a")){ System.out.println("请输入准考证号:"); String examCard = scanner.next(); String sql = "select FlowID flowID,Type type,IDCard,ExamCard examCard,StudentName name,Location location,Grade grade from examstudent where examCard = ?"; Student student = getInstance(Student.class,sql,examCard); if(student != null){ System.out.println(student); }else{ System.out.println("输入的准考证号有误!"); } }else if("b".equalsIgnoreCase(selection)){ System.out.println("请输入身份证号:"); String IDCard = scanner.next(); String sql = "select FlowID flowID,Type type,IDCard,ExamCard examCard,StudentName name,Location location,Grade grade from examstudent where IDCard = ?"; Student student = getInstance(Student.class,sql,IDCard); if(student != null){ System.out.println(student); }else{ System.out.println("输入的身份证号有误!"); } }else{ System.out.println("您的输入有误,请重新进入程序。"); } } public <T> T getInstance(Class<T> clazz,String sql, Object... args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtils.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); // 获取结果集的元数据 :ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData(); // 通过ResultSetMetaData获取结果集中的列数 int columnCount = rsmd.getColumnCount(); if (rs.next()) { T t = clazz.newInstance(); // 处理结果集一行数据中的每一个列 for (int i = 0; i < columnCount; i++) { // 获取列值 Object columValue = rs.getObject(i + 1); // 获取每个列的列名 // String columnName = rsmd.getColumnName(i + 1); String columnLabel = rsmd.getColumnLabel(i + 1); // 给t对象指定的columnName属性,赋值为columValue:通过反射 Field field = clazz.getDeclaredField(columnLabel); field.setAccessible(true); field.set(t, columValue); } return t; } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.closeResource(conn, ps, rs); } return null; }
代码实现3:完成学生信息的删除功能
//问题3:删除指定的学生信息 @Test public void testDeleteByExamCard(){ System.out.println("请输入学生的考号:"); Scanner scanner = new Scanner(System.in); String examCard = scanner.next(); //查询指定准考证号的学生 String sql = "select FlowID flowID,Type type,IDCard,ExamCard examCard,StudentName name,Location location,Grade grade from examstudent where examCard = ?"; Student student = getInstance(Student.class,sql,examCard); if(student == null){ System.out.println("查无此人,请重新输入"); }else{ String sql1 = "delete from examstudent where examCard = ?"; int deleteCount = update(sql1, examCard); if(deleteCount > 0){ System.out.println("删除成功"); } } } //优化以后的操作: @Test public void testDeleteByExamCard1(){ System.out.println("请输入学生的考号:"); Scanner scanner = new Scanner(System.in); String examCard = scanner.next(); String sql = "delete from examstudent where examCard = ?"; int deleteCount = update(sql, examCard); if(deleteCount > 0){ System.out.println("删除成功"); }else{ System.out.println("查无此人,请重新输入"); } }