连接mysql 
uesr:root
password:root
package com.exzample.jdbc1;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.sql.Driver;import java.sql.DriverManager;import java.sql.SQLException;import java.util.Properties;import org.junit.Test;public class ConnectionTest {// 方式一:@Testpublic void testConnection1() throws SQLException {// 获取Driver实现类对象Driver driver = new com.mysql.cj.jdbc.Driver();// url:http://localhost:8080/gmall/keyboard.jpg// jdbc:mysql:协议// localhost:ip地址// 3306:默认mysql的端口号// test:test数据库String url = "jdbc:mysql://localhost:3306/test";// 将用户名和密码封装在Properties中Properties info = new Properties();info.setProperty("user", "root");info.setProperty("password", "root");Connection conn = driver.connect(url, info);System.out.println(conn);}// 方式二:对方式一的迭代:在如下的程序中不出现第三方的api,使得程序具有更好的可移植性@Testpublic void testConnection2() throws Exception {// 1.获取Driver实现类对象:使用反射Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");Driver driver = (Driver) clazz.newInstance();// 2.提供要连接的数据库String url = "jdbc:mysql://localhost:3306/test";// 3.提供连接需要的用户名和密码Properties info = new Properties();info.setProperty("user", "root");info.setProperty("password", "root");// 4.获取连接Connection conn = driver.connect(url, info);System.out.println(conn);}// 方式三:使用DriverManager替换Driver@Testpublic void testConnection3() throws Exception {// 1.获取Driver实现类的对象Class clazz = Class.forName("com.mysql.cj.jdbc.Driver");Driver driver = (Driver) clazz.newInstance();// 2.提供另外三个连接的基本信息:String url = "jdbc:mysql://localhost:3306/test";String user = "root";String password = "root";// 注册驱动DriverManager.registerDriver(driver);// 获取连接Connection conn = DriverManager.getConnection(url, user, password);System.out.println(conn);}// 方式四:可以只是加载驱动,不用显示的注册驱动过了。@Testpublic void testConnection4() throws Exception {// 1.提供三个连接的基本信息:String url = "jdbc:mysql://localhost:3306/test";String user = "root";String password = "root";// 2.加载DriverClass.forName("com.mysql.cj.jdbc.Driver");//相较于方式三,可以省略如下的操作:// Driver driver = (Driver) clazz.newInstance();// // 注册驱动// DriverManager.registerDriver(driver);//为什么可以省略上述操作呢?/** 在mysql的Driver实现类中,声明了如下的操作:* static {try {java.sql.DriverManager.registerDriver(new Driver());} catch (SQLException E) {throw new RuntimeException("Can't register driver!");}}*/// 3.获取连接Connection conn = DriverManager.getConnection(url, user, password);System.out.println(conn);}//方式五(final版):将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接/** 此种方式的好处?* 1.实现了数据与代码的分离。实现了解耦* 2.如果需要修改配置文件信息,可以避免程序重新打包。*/@Testpublic void getConnection5() throws Exception{//1.读取配置文件中的4个基本信息InputStream is = ConnectionTest.class.getClassLoader().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);System.out.println(conn);}}
配置文件
user=rootpassword=rooturl=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=truedriverClass=com.mysql.cj.jdbc.Driver
PreparedStatement
概念:
3.3 PreparedStatement的使用
3.3.1 PreparedStatement介绍
可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的
setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1
开始),第二个是设置的 SQL 语句中的参数的值
3.3.2 PreparedStatement vs Statement
代码的可读性和可维护性。
PreparedStatement 能最大可能提高性能:
DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的
编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参
数直接传入编译过的语句执行代码中就会得到执行。
在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意
义.事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
(语法检查,语义检查,翻译成二进制命令,缓存)
PreparedStatement 可以防止 SQL 注入
3.4 ResultSet与ResultSetMetaData
3.4.1 ResultSet
查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现
ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象
的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。
相当于Iterator对象的 hasNext() 和 next() 方法的结合体。
当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。
例如: getInt(1), getString(“name”)
注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。
ResultSet 接口的常用方法:
boolean next()
getString()
…
3.4.2 ResultSetMetaData
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
ResultSetMetaData meta = rs.getMetaData();
getColumnName(int column):获取指定列的名称
getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
isNullable(int column):指示指定列中的值是否可以为 null。
isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的
3.5 资源的释放
释放ResultSet, Statement,Connection。
数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将
导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
可以在finally中关闭,保证及时其他代码出现异常,资源也一定能被关闭。
3.6 JDBC API小结
两种思想
面向接口编程的思想
ORM思想(object relational mapping)
一个数据表对应一个java类
表中的一条记录对应java类的一个对象
表中的一个字段对应java类的一个属性
sql是需要结合列名和表的属性名来写。注意起别名。
两种技术
JDBC结果集的元数据:ResultSetMetaData
获取列数:getColumnCount()
获取列的别名:getColumnLabel()
通过反射,创建指定类的对象,获取指定的属性并赋值
throws
package com.exzample.jdbc1;import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Properties;import java.util.logging.SimpleFormatter;public class PreparedStatement {public void update() throws Exception{//1.读取配置文件中的4个基本信息InputStream is = ConnectionTest.class.getClassLoader().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);System.out.println(conn);//4.预编译sql语句,返回PreparedStatement实例String sql = "insert into customers(name,email,birth)value(?,?,?)";java.sql.PreparedStatement ps = conn.prepareStatement(sql);//5.填充占位符(?)ps.setString(1,"娜美");ps.setString(2,"134@qq.com");SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");Date date = simpleDateFormat.parse("1234-02-03");ps.setDate(3,new java.sql.Date(date.getTime()));//6.执行操作ps.execute();//7.关闭连接ps.close();conn.close();}}
try-catch
快捷键ctrl-alt-t
package com.exzample.jdbc1;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Properties;import java.util.logging.SimpleFormatter;public class PreparedStatement {public void update(){Connection conn = null;java.sql.PreparedStatement ps = null;try {//1.读取配置文件中的4个基本信息InputStream is = ConnectionTest.class.getClassLoader().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)value(?,?,?)";ps = conn.prepareStatement(sql);//5.填充占位符(?)ps.setString(1,"娜美");ps.setString(2,"134@qq.com");SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");Date date = simpleDateFormat.parse("1234-02-03");ps.setDate(3,new java.sql.Date(date.getTime()));//6.执行操作ps.execute();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} catch (ParseException e) {e.printStackTrace();}finally {//7.关闭连接try {if (ps!=null)ps.close();} catch (SQLException throwables) {throwables.printStackTrace();}try {if (conn!=null)conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}
JDBCutil工具类
package com.exzample.jdbc1;import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;import java.util.Properties;/*JDBC工具类*/public class JDBCUtil {public static Connection getConnetion()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;}public static void closeConnection(Connection conn, PreparedStatement ps){try {if (ps!=null)ps.close();} catch (SQLException throwables) {throwables.printStackTrace();}try {if (conn!=null)conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}

使用PreparedStatement实现增删改通用代码
//通用的增、删、改操作(体现一:增、删、改 ; 体现二:针对于不同的表)public void update(String sql,Object ... args){Connection conn = null;PreparedStatement ps = null;try {//1.获取数据库的连接conn = JDBCUtils.getConnection();//2.获取PreparedStatement的实例 (或:预编译sql语句)ps = conn.prepareStatement(sql);//3.填充占位符for(int i = 0;i < args.length;i++){ps.setObject(i + 1, args[i]);}//4.执行sql语句ps.execute();} catch (Exception e) {e.printStackTrace();}finally{//5.关闭资源JDBCUtils.closeResource(conn, ps);}}

使用PreparedStatement实现查询功能
ORM编程思想
CustomerBeen:
OrderBeen:
package com.exzample;//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//import java.sql.Date;public class Order {private int orderId;private String orderName;private Date orderDate;public Order() {}public Order(int orderId, String orderName, Date orderDate) {this.orderId = orderId;this.orderName = orderName;this.orderDate = orderDate;}public int getOrderId() {return this.orderId;}public void setOrderId(int orderId) {this.orderId = orderId;}public String getOrderName() {return this.orderName;}public void setOrderName(String orderName) {this.orderName = orderName;}public Date getOrderDate() {return this.orderDate;}public void setOrderDate(Date orderDate) {this.orderDate = orderDate;}public String toString() {return "Order [orderId=" + this.orderId + ", orderName=" + this.orderName + ", orderDate=" + this.orderDate + "]";}}
queryForCustomers or Order通用代码:
package com.exzample.jdbc1;import com.exzample.Customer;import org.junit.Test;import java.lang.reflect.Field;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;public class SelectORM {@Testpublic void testqueryForCustomers(){String sql = "select id,name,birth,email from customers where id = ?";Customer customer = queryForCustomers(sql, 1);System.out.println(customer);}public Customer queryForCustomers(String sql, Object...args){Connection conn = null;PreparedStatement ps = null;ResultSet resultSet = null;try {// 1.获取数据库连接conn = JDBCUtil.getConnetion();// 2.预编译sql语句,得到PreparedStatement对象ps = conn.prepareStatement(sql);// 3.填充占位符for (int i = 0;i<args.length;i++){ps.setObject(i+1,args[i]);}// 4.执行executeQuery(),得到结果集:ResultSetresultSet = ps.executeQuery();// 5.得到结果集的元数据:ResultSetMetaDataResultSetMetaData rsmd = resultSet.getMetaData();// 6.1通过ResultSetMetaData得到columnCount,columnLabel;通过ResultSet得到列值int columnCount = rsmd.getColumnCount();if (resultSet.next()){Customer customer = new Customer();for (int i = 0;i<columnCount;i++){// 遍历每一个列// 获取列值Object columValue = resultSet.getObject(i + 1);//获取每个列的列名String columnName = rsmd.getColumnName(i + 1);//给customer对象指定的某个属性,赋值为value,赋值为columValueField field = Customer.class.getDeclaredField(columnName);field.setAccessible(true);field.set(customer,columValue);}return customer;}} catch (Exception e) {e.printStackTrace();} finally {JDBCUtil.closeConnection(conn,ps,resultSet);}return null;}@Testpublic void testOrderForQuery() {String sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_id = ?";Order order = this.orderForQuery(sql, 1);System.out.println(order);}public Order orderForQuery(String sql, Object... args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JDBCUtil.getConnetion();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) {Object columnValue = rs.getObject(i + 1);String columnLabel = rsmd.getColumnLabel(i + 1);Field field = Order.class.getDeclaredField(columnLabel);field.setAccessible(true);field.set(order, columnValue);}return order;}} catch (Exception var17) {var17.printStackTrace();} finally {JDBCUtil.closeConnection(conn, ps, rs);}return null;}}
Test结果:

拓展:PreparedStatement针对不同表的的通用查询(返回一条记录or多条记录)
package com.atguigu3.preparedstatement.crud;import com.atguigu3.bean.Customer;import com.atguigu3.bean.Order;import com.atguigu3.util.JDBCUtils;import java.lang.reflect.Field;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.util.ArrayList;import java.util.List;import org.junit.Test;public class PreparedStatementQueryTest {public PreparedStatementQueryTest() {}@Testpublic void testGetForList() {String sql = "select id,name,email from customers where id < ?";List<Customer> list = this.getForList(Customer.class, sql, 12);list.forEach(System.out::println);String sql1 = "select order_id orderId,order_name orderName from `order`";List<Order> orderList = this.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 rsmd = rs.getMetaData();int columnCount = rsmd.getColumnCount();ArrayList list = new ArrayList();while(rs.next()) {T t = clazz.newInstance();for(int i = 0; i < columnCount; ++i) {Object columValue = rs.getObject(i + 1);String columnLabel = rsmd.getColumnLabel(i + 1);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;}@Testpublic void testGetInstance() {String sql = "select id,name,email from customers where id = ?";Customer customer = (Customer)this.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 = (Order)this.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 = 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()) {T t = clazz.newInstance();for(int i = 0; i < columnCount; ++i) {Object columValue = rs.getObject(i + 1);String columnLabel = rsmd.getColumnLabel(i + 1);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;}}
PreparedStatement解决sql注入问题:
package com.atguigu2.statement.crud;import com.atguigu3.util.JDBCUtils;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;public class PreparedStatementTest {public PreparedStatementTest() {}@Testpublic void testLogin() {Scanner scanner = new Scanner(System.in);System.out.print("请输入用户名:");String user = scanner.nextLine();System.out.print("请输入密码:");String password = scanner.nextLine();String sql = "SELECT user,password FROM user_table WHERE user = ? and password = ?";User returnUser = (User)this.getInstance(User.class, sql, user, password);if (returnUser != null) {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 rsmd = rs.getMetaData();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 columnLabel = rsmd.getColumnLabel(i + 1);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;}}
exer1
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();//'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;}}
exer2
public class Exer2Test {public Exer2Test() {}@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 = this.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 {conn = JDBCUtils.getConnection();ps = conn.prepareStatement(sql);for(int i = 0; i < args.length; ++i) {ps.setObject(i + 1, args[i]);}int var7 = ps.executeUpdate();return var7;} catch (Exception var10) {var10.printStackTrace();} finally {JDBCUtils.closeResource(conn, ps);}return 0;}@Testpublic void queryWithIDCardOrExamCard() {System.out.println("请选择您要输入的类型:");System.out.println("a.准考证号");System.out.println("b.身份证号");Scanner scanner = new Scanner(System.in);String selection = scanner.next();String IDCard;String sql;Student student;if ("a".equalsIgnoreCase(selection)) {System.out.println("请输入准考证号:");IDCard = scanner.next();sql = "select FlowID flowID,Type type,IDCard,ExamCard examCard,StudentName name,Location location,Grade grade from examstudent where examCard = ?";student = (Student)this.getInstance(Student.class, sql, IDCard);if (student != null) {System.out.println(student);} else {System.out.println("输入的准考证号有误!");}} else if ("b".equalsIgnoreCase(selection)) {System.out.println("请输入身份证号:");IDCard = scanner.next();sql = "select FlowID flowID,Type type,IDCard,ExamCard examCard,StudentName name,Location location,Grade grade from examstudent where IDCard = ?";student = (Student)this.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 rsmd = rs.getMetaData();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 columnLabel = rsmd.getColumnLabel(i + 1);Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columValue);}return t;}} catch (Exception var18) {var18.printStackTrace();} finally {JDBCUtils.closeResource(conn, ps, rs);}return null;}@Testpublic 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 = (Student)this.getInstance(Student.class, sql, examCard);if (student == null) {System.out.println("查无此人,请重新输入");} else {String sql1 = "delete from examstudent where examCard = ?";int deleteCount = this.update(sql1, examCard);if (deleteCount > 0) {System.out.println("删除成功");}}}@Testpublic void testDeleteByExamCard1() {System.out.println("请输入学生的考号:");Scanner scanner = new Scanner(System.in);String examCard = scanner.next();String sql = "delete from examstudent where examCard = ?";int deleteCount = this.update(sql, examCard);if (deleteCount > 0) {System.out.println("删除成功");} else {System.out.println("查无此人,请重新输入");}}}
PreparedStatement vs Statement两大优点体现:
4.1 MySQL BLOB类型
MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。
插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。
MySQL的四种BLOB类型(除了在存储的最大信息量上不同外,他们是等同的)
实际使用中根据需要存入的数据大小定义不同的BLOB类型。
需要注意的是:如果存储的文件过大,数据库的性能会下降。如果在指定了相关的Blob类型以后,还报错:xxx too large,那么在mysql的安装目录下,找my.ini文件加上如
下的配置参数: max_allowed_packet=16M。同时注意:修改了my.ini文件之后,需要重新启动mysql服务。
/**** @Description 测试使用PreparedStatement操作Blob类型的数据* @author shkstart Email:shkstart@126.com* @version* @date 下午4:08:58**/public class BlobTest {//向数据表customers中插入Blob类型的字段@Testpublic void testInsert() throws Exception{Connection conn = JDBCUtils.getConnection();String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";PreparedStatement ps = conn.prepareStatement(sql);ps.setObject(1,"袁浩");ps.setObject(2, "yuan@qq.com");ps.setObject(3,"1992-09-08");FileInputStream is = new FileInputStream(new File("girl.jpg"));ps.setBlob(4, is);ps.execute();JDBCUtils.closeResource(conn, ps);}//查询数据表customers中Blob类型的字段@Testpublic void testQuery(){Connection conn = null;PreparedStatement ps = null;InputStream is = null;FileOutputStream fos = null;ResultSet rs = null;try {conn = JDBCUtils.getConnection();String sql = "select id,name,email,birth,photo from customers where id = ?";ps = conn.prepareStatement(sql);ps.setInt(1, 21);rs = ps.executeQuery();if(rs.next()){// 方式一:// int id = rs.getInt(1);// String name = rs.getString(2);// String email = rs.getString(3);// Date birth = rs.getDate(4);//方式二:int id = rs.getInt("id");String name = rs.getString("name");String email = rs.getString("email");Date birth = rs.getDate("birth");Customer cust = new Customer(id, name, email, birth);System.out.println(cust);//将Blob类型的字段下载下来,以文件的方式保存在本地Blob photo = rs.getBlob("photo");is = photo.getBinaryStream();fos = new FileOutputStream("zhangyuhao.jpg");byte[] buffer = new byte[1024];int len;while((len = is.read(buffer)) != -1){fos.write(buffer, 0, len);}}} catch (Exception e) {e.printStackTrace();}finally{try {if(is != null)is.close();} catch (IOException e) {e.printStackTrace();}try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}JDBCUtils.closeResource(conn, ps, rs);}}}
5.1 批量执行SQL语句
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处
理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch():执行批量处理语句;
clearBatch():清空缓存的数据
通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理;
一个SQL语句的批量传参;
/** 使用PreparedStatement实现批量数据的操作** update、delete本身就具有批量操作的效果。* 此时的批量操作,主要指的是批量插入。使用PreparedStatement如何实现更高效的批量插入?** 题目:向goods表中插入20000条数据* CREATE TABLE goods(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(25));* 方式一:使用Statement* Connection conn = JDBCUtils.getConnection();* Statement st = conn.createStatement();* for(int i = 1;i <= 20000;i++){* String sql = "insert into goods(name)values('name_" + i + "')";* st.execute(sql);* }**/public class InsertTest {//批量插入的方式二:使用PreparedStatement@Testpublic void testInsert1() {Connection conn = null;PreparedStatement ps = null;try {long start = System.currentTimeMillis();conn = JDBCUtils.getConnection();String sql = "insert into goods(name)values(?)";ps = conn.prepareStatement(sql);for(int i = 1;i <= 20000;i++){ps.setObject(1, "name_" + i);ps.execute();}long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));//20000:83065} catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.closeResource(conn, ps);}}/** 批量插入的方式三:* 1.addBatch()、executeBatch()、clearBatch()* 2.mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。* ?rewriteBatchedStatements=true 写在配置文件的url后面* 3.使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar*/@Testpublic void testInsert2() {Connection conn = null;PreparedStatement ps = null;try {long start = System.currentTimeMillis();conn = JDBCUtils.getConnection();String sql = "insert into goods(name)values(?)";ps = conn.prepareStatement(sql);for(int i = 1;i <= 1000000;i++){ps.setObject(1, "name_" + i);//1."攒"sqlps.addBatch();if(i % 500 == 0){//2.执行batchps.executeBatch();//3.清空batchps.clearBatch();}}long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565} catch (Exception e) { //1000000:16086e.printStackTrace();}finally{JDBCUtils.closeResource(conn, ps);}}//批量插入的方式四:设置连接不允许自动提交数据@Testpublic void testInsert3() {Connection conn = null;PreparedStatement ps = null;try {long start = System.currentTimeMillis();conn = JDBCUtils.getConnection();//设置不允许自动提交数据conn.setAutoCommit(false);String sql = "insert into goods(name)values(?)";ps = conn.prepareStatement(sql);for(int i = 1;i <= 1000000;i++){ps.setObject(1, "name_" + i);//1."攒"sqlps.addBatch();if(i % 500 == 0){//2.执行batchps.executeBatch();//3.清空batchps.clearBatch();}}//提交数据conn.commit();long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565} catch (Exception e) { //1000000:16086 -- 5114e.printStackTrace();}finally{JDBCUtils.closeResource(conn, ps);}}}
