连接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 {
// 方式一:
@Test
public 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,使得程序具有更好的可移植性
@Test
public 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
@Test
public 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);
}
// 方式四:可以只是加载驱动,不用显示的注册驱动过了。
@Test
public void testConnection4() throws Exception {
// 1.提供三个连接的基本信息:
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "root";
// 2.加载Driver
Class.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.如果需要修改配置文件信息,可以避免程序重新打包。
*/
@Test
public 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=root
password=root
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
driverClass=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 {
@Test
public 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(),得到结果集:ResultSet
resultSet = ps.executeQuery();
// 5.得到结果集的元数据:ResultSetMetaData
ResultSetMetaData 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,赋值为columValue
Field 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;
}
@Test
public 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() {
}
@Test
public 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;
}
@Test
public 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() {
}
@Test
public 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 {
@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;
}
}
exer2
public class Exer2Test {
public Exer2Test() {
}
@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 = 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;
}
@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();
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;
}
@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 = (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("删除成功");
}
}
}
@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 = 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类型的字段
@Test
public 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类型的字段
@Test
public 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
@Test
public 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
*/
@Test
public 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."攒"sql
ps.addBatch();
if(i % 500 == 0){
//2.执行batch
ps.executeBatch();
//3.清空batch
ps.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565
} catch (Exception e) { //1000000:16086
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, ps);
}
}
//批量插入的方式四:设置连接不允许自动提交数据
@Test
public 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."攒"sql
ps.addBatch();
if(i % 500 == 0){
//2.执行batch
ps.executeBatch();
//3.清空batch
ps.clearBatch();
}
}
//提交数据
conn.commit();
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565
} catch (Exception e) { //1000000:16086 -- 5114
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, ps);
}
}
}