JDBC-day02(使用PreparedStatement实现CRUD操作)

所需的数据库数据要导入到自己的数据库库中

三:使用PreparedStatement实现CRUD操作

  • 数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数据库连接就是一个Socket连接
  • CRUD操作:根据返回值的有无可分为两类
    • 删除,添加,修改
    • 查询
  • 在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
    • Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
    • PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
    • CallableStatement:用于执行 SQL 存储过程

1.Statement类(可略过)

示例代码

public class User {private String user;private String password; public User() {}public User(String user, String password) {super();this.user = user;this.password = password;}@Overridepublic String toString() {return "User [user=" + user + ", password=" + password + "]";}public String getUser() {return user;}public void setUser(String user) {this.user = user;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;      
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner;import org.junit.Test;public class StatementTest {@Testpublic void testLogin() {Scanner scan = new Scanner(System.in);System.out.print("用户名:");String userName = scan.nextLine();System.out.print("密   码:");String password = scan.nextLine();// SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '// ='1' or '1' = '1';String sql = "SELECT user,password FROM user_table WHERE user = ? and password = ?";User user = get(sql, User.class);if (user != null) {System.out.println("登陆成功!");} else {System.out.println("用户名或密码错误!");}}// 使用Statement实现对数据表的查询操作public <T> T get(String sql, Class<T> clazz) {T t = null;Connection conn = null;Statement st = null;ResultSet rs = null;try {// 1.加载配置文件InputStream is = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties");Properties pros = new Properties();pros.load(is);// 2.读取配置信息String user = pros.getProperty("user");String password = pros.getProperty("password");String url = pros.getProperty("url");String driverClass = pros.getProperty("driverClass");// 3.加载驱动Class.forName(driverClass);// 4.获取连接conn = DriverManager.getConnection(url, user, password);st = conn.createStatement();rs = st.executeQuery(sql);// 获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();// 获取结果集的列数int columnCount = rsmd.getColumnCount();if (rs.next()) {t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// //1. 获取列的名称// String columnName = rsmd.getColumnName(i+1);// 1. 获取列的别名String columnName = rsmd.getColumnLabel(i + 1);// 2. 根据列名获取对应数据表中的数据Object columnVal = rs.getObject(columnName);// 3. 将数据表中得到的数据,封装进对象Field field = clazz.getDeclaredField(columnName);field.setAccessible(true);field.set(t, columnVal);}return t;}} catch (Exception e) {e.printStackTrace();} finally {// 关闭资源if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if (st != null) {try {st.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}return null;}}
  • 上面的代码有两个问题
    • 问题一:存在拼串操作
      在SQL语句的编写中存在拼串的操作
    • 问题二:存在SQL注入问题
      在用户输入数据中注入非法的 SQL 语句段或命令
      (如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1')

使用PreparedStatement(从Statement扩展而来) 取代 Statement 就可以防范 SQL 注入
使用PreparStatement取代Statement
代码优化见8.user查询的优化

2.PreparedStatement类

  • 可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象

  • PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句

  • PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值

3.Java与SQL对应数据类型转换表

Java类型SQL类型
booleanBIT
byteTINYINT
shortSMALLINT
intINTEGER
longBIGINT
StringCHAR,VARCHAR,LONGVARCHAR
byte arrayBINARY , VAR BINARY
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP

4.使用PreparedStatement类完成Customers表的增删改操作

增删改操作类似下面的案例都是以增数据为例
customers表中添加一条记录
**例:此处以添加为例

	@Testpublic void testInsert() {Connection conn = null;                    PreparedStatement ps = null;try {//1.读取配置文件中的配置信息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);//4.预编译sql语句,返回PreparedStatement的实例String sql = "insert into customers(name,email,birth)values(?,?,?)";//?:占位符ps = conn.prepareStatement(sql);//5.填充占位符ps.setString(1, "邓紫棋");ps.setString(2, "GM@gmail.com");SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");java.util.Date date = sdf.parse("2001-09-15");ps.setDate(3, new Date(date.getTime()));//6.执行SQL操作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(Exception e) {e.printStackTrace();}}}

5.使用PreparedStatement类完成Customers表的增删改操作(上一步的优化)

将通用的连接与关闭资源写成一个工具类

import java.io.InputStream;
import java.sql.Connection;                   
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
//操作数据库的工具类
public class JDBC_Utils {//获取数据库连接public static Connection getConnection() throws Exception {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");Class.forName(driverClass);Connection conn = DriverManager.getConnection(url,user,password);return conn;}//关闭连接与Statement资源的操作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(Exception e) {e.printStackTrace();}}
}

上面的类命名时最好不要带下滑线,对测试customers表中添加一条记录

	@Testpublic void testUpdate(){	Connection conn = null;      PreparedStatement ps = null;try {//1.连接数据库conn = JDBC_Utils.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.执行SQL语言ps.execute();} catch (Exception e) {e.printStackTrace();}finally {//5.资源关闭JDBC_Utils.closeResource(conn, ps);}
}

6.使用PreparedStatement类完成Customers表的增删改通用操作

public class UpdateTest {//通用的增删改操作@Testpublic void testCommonUpdate() {
//		String sql = "delete from customers where id = ?";               
//		update(sql,3);String sql = "update `order` set order_name = ? where order_id = ?";//当表名与关键字重合,可以用` `在SQL语句中加以区分update(sql,"DD","2");}public void update(String sql,Object ...args) {Connection conn = null;PreparedStatement ps = null;try {//1.获取数据库的连接conn = JDBC_Utils.getConnection();//2.预编译SQL语句ps = conn.prepareStatement(sql);//3.填充占位符(可变形参长度与SQL占位符数量一致)for(int i = 0;i < args.length;i++) {ps.setObject(i + 1,args[i]);//小心参数声明错误(从1开始)}//4.执行ps.execute();} catch (Exception e) {e.printStackTrace();}finally {//5.关闭资源JDBC_Utils.closeResource(conn, ps);}}
}

7.使用PreparedStatement类完成Customers表查询操作(单条数据)

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;public Customer() {super();}public Customer(int id, String name, String email, Date birth) {super();this.id = id;this.name = name;this.email = email;this.birth = birth;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "Customer [id=" + id + ", name=" + name + ", email=" + email + ", birth=" + birth + "]";}
}

例:对customers表进行单条查询操作

	@Testpublic void testQuery1() {Connection conn = null;      PreparedStatement ps = null;ResultSet resultSet = null;try {conn = JDBC_Utils.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 {//关闭资源JDBC_Utils.closeResource(conn, ps,resultSet);}}

8.使用PreparedStatement类完成Customers表查询通用操作(单条数据)

针对表的字段名与类的属性名不同的情况(如:针对Order表的通用的查询操作)

  • 1.必须在声明SQL时,使用类的属性名来命名表中字段的别名
  • 2.使用ResultSetMetaData时,需要使用getColumnLabel()来替换getColumnName()获得列的列名
  • 3.如果sql中没有给字段起别名时,查询的就是列的列名

例:针对Customers表的查询操作


public class CustomersQuery {@Testpublic void testQueryForCustomers() {
//		String sql = "select id,name,email,birth from customers where id = ?";                                   
//		Customer customer = queryForCustomers(sql,13);
//		System.out.println(customer);String sql = "select id,name,email,birth from customers where name = ?";Customer customer = queryForCustomers(sql,"周杰伦");System.out.println(customer);}/**针对customers表的通用操作 */public Customer queryForCustomers(String sql,Object ...args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBC_Utils.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();//通过ResultSetMetaData获取结果集中的列数int columnCount = rsmd.getColumnCount();if(rs.next()) {Customer cust = new Customer();for(int i = 0;i < columnCount;i++) {//获取列值:结果集Object columnvalue = rs.getObject(i +1);//获取每个列的列名:结果集元数据
//					String columnName = rsmd.getColumnName(i + 1);//获取每个列的别名(无别名就获取表的列名):结果集元数据String columnLabel = rsmd.getColumnLabel(i + 1);//给cust指定columnName属性赋值为columnvalue,通过反射Field field = Customer.class.getDeclaredField(columnLabel);field.setAccessible(true);field.set(cust, columnvalue);}return cust;}}catch (Exception e) {e.printStackTrace();}finally {JDBC_Utils.closeResource(conn, ps, rs);}return null;}

例:针对Order表的通用的查询操作
order类

import java.sql.Date;public class Order {private int orderId;      private String orderName;private Date orderDate;public Order() {super();}public Order(int orderId, String orderName, Date orderDate) {super();this.orderId = orderId;this.orderName = orderName;this.orderDate = orderDate;}public int getOrderId() {return orderId;}public void setOrderId(int orderId) {this.orderId = orderId;}public String getOrderName() {return orderName;}public void setOrderName(String orderName) {this.orderName = orderName;}public Date getOrderDate() {return orderDate;}public void setOrderDate(Date orderDate) {this.orderDate = orderDate;}@Overridepublic String toString() {return "Order [orderId=" + orderId + ", orderName=" + orderName + ", orderDate=" + orderDate + "]";}}

查询操作


import java.lang.reflect.Field;
import java.sql.Connection;        
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;import org.junit.Test;import com.jdbc.util.JDBC_Utils;/*** 针对于Order表的通用的查询操作*/
public class OrderForQuery {@Testpublic 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);}/*** 通用的针对于order表的查询操作*/public Order orderForQuery(String sql,Object...args){Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBC_Utils.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++){//获取每个列的列值:通过ResultSetObject columnValue = rs.getObject(i + 1);//通过ResultSetMetaData//获取列的列名:getColumnName() --不推荐使用//获取列的别名:getColumnLabel()
//					String columnName = rsmd.getColumnName(i + 1);String columnLabel = rsmd.getColumnLabel(i + 1);//通过反射,将对象指定名columnName的属性赋值为指定的值columnValueField field = Order.class.getDeclaredField(columnLabel);field.setAccessible(true);field.set(order, columnValue);}return order;}} catch (Exception e) {e.printStackTrace();}finally{JDBC_Utils.closeResource(conn, ps, rs);}return null;}@Testpublic void testQuery1(){Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBC_Utils.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{JDBC_Utils.closeResource(conn, ps, rs);}}}

9.针对不同表不同字段的查询通用操作

针对不同表不同字段的查询通用操作,此时返回表中的一条记录

	@Testpublic void test1() {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);}public <T> T getInstance(Class<T> clazz,String sql,Object ...args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBC_Utils.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();//通过ResultSetMetaData获取结果集中的列数int columnCount = rsmd.getColumnCount();if(rs.next()) {T t = clazz.newInstance();for(int i = 0;i < columnCount;i++) {//获取列值:结果集Object columnvalue = rs.getObject(i +1);//获取每个列的列名:结果集元数据
//					String columnName = rsmd.getColumnName(i + 1);//获取每个列的别名(无别名就获取表的列名):结果集元数据String columnLabel = rsmd.getColumnLabel(i + 1);//给cust指定columnName属性赋值为columnvalue,通过反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnvalue);}return t;}}catch (Exception e) {e.printStackTrace();}finally {JDBC_Utils.closeResource(conn, ps, rs);}return null;}

针对不同表不同字段的查询通用操作,返回多条数据

public class PreparedStatementQeryTest {@Testpublic 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> list1 = getForList(Order.class,sql1);list1.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 = JDBC_Utils.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();//通过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 columnvalue = rs.getObject(i +1);//获取每个列的列名:结果集元数据
//					String columnName = rsmd.getColumnName(i + 1);//获取每个列的别名(无别名就获取表的列名):结果集元数据String columnLabel = rsmd.getColumnLabel(i + 1);//给cust指定columnName属性赋值为columnvalue,通过反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnvalue);}list.add(t);}return list;}catch (Exception e) {e.printStackTrace();}finally {JDBC_Utils.closeResource(conn, ps, rs);}return null;}
}

增删改类似

10.user查询的优化

import java.lang.reflect.Field;
import java.sql.Connection;            
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Scanner;import org.junit.Test;import com.jdbc.util.JDBC_Utils;
public class PreparedStatementTest {@Testpublic void testLogin() {Scanner scan = new Scanner(System.in);System.out.print("用户名:");String userName = scan.nextLine();System.out.print("密   码:");String password = scan.nextLine();// SELECT user,password FROM user_table WHERE USER = '1' or ' AND PASSWORD = '// ='1' or '1' = '1';String sql = "SELECT user,password FROM user_table WHERE USER = ? and password = ?";User user = getInstance(User.class, sql,userName,password);if (user != null) {System.out.println("登陆成功!");} else {System.out.println("用户名或密码错误!");}}//使用PreparedStatement针对不同表不同字段的查询通用操作,此时返回表中的一条记录public <T> T getInstance(Class<T> clazz,String sql,Object ...args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBC_Utils.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();//通过ResultSetMetaData获取结果集中的列数int columnCount = rsmd.getColumnCount();if(rs.next()) {T t = clazz.newInstance();for(int i = 0;i < columnCount;i++) {//获取列值:结果集Object columnvalue = rs.getObject(i +1);//获取每个列的列名:结果集元数据
//					String columnName = rsmd.getColumnName(i + 1);//获取每个列的别名(无别名就获取表的列名):结果集元数据String columnLabel = rsmd.getColumnLabel(i + 1);//给cust指定columnName属性赋值为columnvalue,通过反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnvalue);}return t;}}catch (Exception e) {e.printStackTrace();}finally {JDBC_Utils.closeResource(conn, ps, rs);}return null;}
}

11.练习

练习一
在这里插入图片描述

import java.sql.Connection;   
import java.sql.PreparedStatement;
import java.util.Scanner;import org.junit.Test;import com.jdbc.util.JDBC_Utils;
public class Exer1Test {@Testpublic 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();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) {Connection conn = null;PreparedStatement ps = null;try {//1.获取数据库的连接conn = JDBC_Utils.getConnection();//2.预编译SQL语句ps = conn.prepareStatement(sql);//3.填充占位符(可变形参长度与SQL占位符数量一致)for(int i = 0;i < args.length;i++) {ps.setObject(i + 1,args[i]);//小心参数声明错误(从1开始)}//4.执行/*** ps.execute():* false:执行的是增,删改操作,无返回值* ture:执行的是查询操作,有返回值*///方式一:
//			return ps.execute();//方式二:return ps.executeUpdate();//返回的是影响的行数} catch (Exception e) {e.printStackTrace();}finally {//5.关闭资源JDBC_Utils.closeResource(conn, ps);}return 0;}
}

练习二
在这里插入图片描述
在这里插入图片描述

Student类

public class Student {private int flowID;//流水号         private int type;//考试类型private String IDCard;//身份证号private String examCard;//准考证号private String name;//学生姓名private String location;//学生所在城市private int grade;//考试成绩public Student() {super();}public Student(int flowID, int type, String iDCard, String examCard, String name, String location, int grade) {super();this.flowID = flowID;this.type = type;IDCard = iDCard;this.examCard = examCard;this.name = name;this.location = location;this.grade = grade;}public int getType() {return type;}public void setType(int type) {this.type = type;}public String getIDCard() {return IDCard;}public void setIDCard(String iDCard) {IDCard = iDCard;}public String getExamCard() {return examCard;}public void setExamCard(String examCard) {this.examCard = examCard;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public int getGrade() {return grade;}public void setGrade(int grade) {this.grade = grade;}public int getFlowID() {return flowID;}@Overridepublic String toString() {System.out.println("===============查询结果===================");return info();}private String info() {return "流水号:" + flowID + "\n四级/六级:" + type + "\n身份证号:" + IDCard + "\n准考证号:" + examCard + "\n学生姓名:" + name + "\n区域:" + location + "\n成绩:" + grade;}}

三个小问题写在一起

mport java.lang.reflect.Field;
import java.sql.Connection; 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Scanner;import org.junit.Test;import com.jdbc.util.JDBC_Utils;
public class Exer1Test2 {//问题1:向examstudent表中添加一条记录@Testpublic 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) {Connection conn = null;PreparedStatement ps = null;try {//1.获取数据库的连接conn = JDBC_Utils.getConnection();//2.预编译SQL语句ps = conn.prepareStatement(sql);//3.填充占位符(可变形参长度与SQL占位符数量一致)for(int i = 0;i < args.length;i++) {ps.setObject(i + 1,args[i]);//小心参数声明错误(从1开始)}//4.执行/*** ps.execute():* false:执行的是增,删改操作,无返回值* ture:执行的是查询操作,有返回值*///方式一:
//			return ps.execute();//方式二:return ps.executeUpdate();//返回的是影响的行数} catch (Exception e) {e.printStackTrace();}finally {//5.关闭资源JDBC_Utils.closeResource(conn, ps);}return 0;}//问题2:根据身份证号或者准考证号查询学生成绩@Testpublic void queryWithID() {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)) {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 = JDBC_Utils.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();//通过ResultSetMetaData获取结果集中的列数int columnCount = rsmd.getColumnCount();if(rs.next()) {T t = clazz.newInstance();for(int i = 0;i < columnCount;i++) {//获取列值:结果集Object columnvalue = rs.getObject(i +1);//获取每个列的列名:结果集元数据
//					String columnName = rsmd.getColumnName(i + 1);//获取每个列的别名(无别名就获取表的列名):结果集元数据String columnLabel = rsmd.getColumnLabel(i + 1);//给cust指定columnName属性赋值为columnvalue,通过反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnvalue);}return t;}}catch (Exception e) {e.printStackTrace();}finally {JDBC_Utils.closeResource(conn, ps, rs);}return null;}//问题三:删除指定的学生信息@Testpublic void testDeletByExamCard() {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 updateCount = update(sql1,examCard);if(updateCount > 0) {System.out.println("删除成功");}else {System.out.println("删除失败,请重新操作");}}}//上一步的优化操作@Testpublic void testdelete() {System.out.println("请输入学生的考号:");Scanner scanner = new Scanner(System.in);String examCard = scanner.next();String sql = "delete from examstudent where examCard = ?";int updateCount = update(sql,examCard);if(updateCount > 0) {System.out.println("删除成功");}else {System.out.println("查无此人,请重新输入");}}
}

其中可能会出现不少的小问题,请多多包含
感谢大家的支持,关注,评论,点赞!
参考资料:尚硅谷_宋红康_JDBC核心技术

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/97153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Go】go-es统计接口被刷数和ip访问来源

go-es模块统计日志中接口被刷数和ip访问来源 以下是使用go的web框架gin作为后端&#xff0c;展示的统计页面 背景 上面的数据来自elk日志统计。因为elk通过kibana进行展示&#xff0c;但是kibana有一定学习成本且不太能满足定制化的需求&#xff0c;所以考虑用编程的方式…

Eclipse iceoryx™ - 真正的零拷贝进程间通信

1 序言 通过一个快速的背景教程&#xff0c;介绍项目范围和安装所需的所有内容以及第一个运行示例。 首先&#xff1a;什么是冰羚&#xff1f; iceoryx是一个用于各种操作系统的进程间通信&#xff08;IPC&#xff09;中间件&#xff08;目前我们支持Linux、macOS、QNX、FreeBS…

C语言中文网 - Shell脚本 - 1

Shell 既是一个连接用户和 Linux 内核的程序&#xff0c;又是一门管理 Linux 系统的脚本语言。Shell 脚本虽然没有 C、Python、Java、C# 等编程语言强大&#xff0c;但也支持了基本的编程元素。 第1章 Shell基础&#xff08;开胃菜&#xff09; 欢迎来到 Linux Shell 的世界&am…

asp.net闲置物品购物网系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net闲置物品购物网系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 asp.net 闲置物品购物网 二、功…

JavaScript中的map()和forEach()方法有什么区别?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

DevEco Studio下载/安装与配置开发环境

一、下载与安装DevEco Studio 在HarmonyOS应用开发学习之前&#xff0c;需要进行一些准备工作&#xff0c;首先需要完成开发工具DevEco Studio的下载与安装以及环境配置。 1.进入DevEco Studio下载官网 单击“立即下载”进入下载页面。 DevEco Studio提供了Windows版本和Mac…

学信息系统项目管理师第4版系列20_风险管理

1. 针对不确定性的应对方法 1.1. 【高23上选58】 1.2. 收集信息 1.2.1. 可以对信息收集和分析工作进行规划&#xff0c;以便发现更多信息&#xff08;如进行研究、争取专家参与或进行市场分析&#xff09;来减少不确定性 1.3. 为多种结果做好准备 1.3.1. 制定可用的解决方…

高级 I/O【Linux】

阅读前导&#xff1a; “高级 I/O”处于知识树中网络和操作系统的最后&#xff0c;因此本文默认读者有计算机网络和操作系统的基础。 1. 什么是 I/O 下面以“流”&#xff08;stream&#xff09;和冯诺依曼体系架构的视角来简单回顾一下什么是 I/O&#xff1a; I/O可以理解…

2023全新小红书图集和视频解析去水印网站源码

2023全新小红书图集和视频解析去水印网站源码 小红书视频图集解析网站源码&#xff0c;在红书看到好看的图片以及好看的头像&#xff0c;但是直接下载又有水印就非常难受&#xff0c;这个可以一键解析去除水印&#xff0c;支持统计解析次数&#xff0c;本地接口。 源码下载&a…

【C++】指针与引用(学习笔记)

一、左值与右值 左值&#xff1a;编译器为其单独分配了一块存储空间&#xff0c;可以取其地址的&#xff0c;可以放在赋值运算符左边 右值&#xff1a;数据本身。不能取到其自身地址&#xff0c;只能赋值运算右边 左值最常见的情况如西数和数据成员的名字 右值是没有标识符、…

k8s 集群安装(vagrant + virtualbox + CentOS8)

主机环境&#xff1a;windows 11 k8s版本&#xff1a;v1.25 dashboard版本&#xff1a;v2.7.0 calico版本&#xff1a; v3.26.1 CentOS8版本&#xff1a;4.18.0-348.7.1.el8_5.x86_64 用到的脚本&#xff1a; https://gitcode.net/sundongsdu/k8s_cluster 1. Vagrant创建…

2023去水印小程序源码修复版-前端后端内置接口+第三方接口

去水印小程序源码&#xff0c;前端后端&#xff0c;内置接口第三方接口&#xff0c;修复数据库账号密码错误问题&#xff0c;内置接口支持替换第三方接口&#xff0c;看了一下文件挺全的&#xff0c;可以添加流量主代码&#xff0c;搭建需要准备一台服务器&#xff0c;备案域名…

论文阅读--Energy efficiency in heterogeneous wireless access networks

异构无线接入网络的能源效率 论文信息&#xff1a;Navaratnarajah S, Saeed A, Dianati M, et al. Energy efficiency in heterogeneous wireless access networks[J]. IEEE wireless communications, 2013, 20(5): 37-43. I. ABSTRACT && INTRODUCTION 本文提出了无…

【虚拟机栈】

文章目录 1. 虚拟机栈概述2. 局部变量表(Local Variables)3. 操作数栈4. 动态链接4.1 方法的调用&#xff1a;解析与分配 1. 虚拟机栈概述 每个线程在创建时都会创建一个虚拟机栈&#xff0c;其内部保存一个个的栈帧&#xff08;Stack Frame&#xff09;&#xff0c;对应着一次…

互联网Java工程师面试题·Redis 篇·第二弹

目录 16、Redis 集群方案什么情况下会导致整个集群不可用&#xff1f; 17、Redis 支持的 Java 客户端都有哪些&#xff1f;官方推荐用哪个&#xff1f; 18、Jedis 与 Redisson 对比有什么优缺点&#xff1f; 19、Redis 如何设置密码及验证密码&#xff1f; 20、说说 Redis…

CSS学习笔记

目录 1.CSS简介1.什么是CSS2.为什么使用CSS3.CSS作用 2.基本用法1.CSS语法2.CSS应用方式1. 内部样式2.行内样式3.外部样式1.使用 link标签 链接外部样式文件2.import 指令 导入外部样式文件3.使用举例 3.选择器1.基础选择器1.标签选择器2.类选择器3.ID选择器4.使用举例 2.复杂选…

【微服务】RedisSearch 使用详解

目录 一、RedisJson介绍 1.1 RedisJson是什么 1.2 RedisJson特点 1.3 RedisJson使用场景 1.3.1 数据结构化存储 1.3.2 实时数据分析 1.3.3 事件存储和分析 1.3.4 文档存储和检索 二、当前使用中的问题 2.1 刚性数据库模式限制了敏捷性 2.2 基于磁盘的文档存储导致瓶…

EasyX图形库note4,动画及键盘交互

大家好&#xff0c;这里是Dark Flame Master&#xff0c;专栏从这篇开始就会变得很有意思&#xff0c;我们可以利用今天所学的只是实现很多功能&#xff0c;同样为之后的更加好玩的内容打下基础&#xff0c;从这届开始将会利用所学的知识制作一些小游戏&#xff0c;废话不多说&…

基于支持向量机SVM和MLP多层感知神经网络的数据预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 一、支持向量机&#xff08;SVM&#xff09; 二、多层感知器&#xff08;MLP&#xff09; 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .…

Go Gin Gorm Casbin权限管理实现 - 3. 实现Gin鉴权中间件

文章目录 0. 背景1. 准备工作2. gin中间件2.1 中间件代码2.2 中间件使用2.3 测试中间件使用结果 3. 添加权限管理API3.1 获取所有用户3.2 获取所有角色组3.3 获取所有角色组的策略3.4 修改角色组策略3.5 删除角色组策略3.6 添加用户到组3.7 从组中删除用户3.8 测试API 4. 最终目…