1 Statement问题分析
既然java.sql包提供有Statement接口实现数据库的操作,那么为什么又要提供一个PreparedStatement接口实现数据库的操作呢?
下面就以更新的操作为例,在Statement接口里面如果想要执行SQL语句,那么一定要通过字符串实现SQL结构的定义,但是这种定义如果要结合到用户输入数据的情况下就有可能会有问题存在了,下面通过一个程序做一个简单的模拟。
范例:分析Statement接口操作问题
package org.lks.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class MySQLJDBCDemo {
private static final String DATABASE_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/research_managerment?useSSL=true&serverTimezone=UTC";
private static final String DATABASE_USER = "root";
private static final String DATABASE_PASSWORD = "19990821";
public static void main(String[] args) throws Exception{
int id = 1002;
String name = "zsl";
String date = "1998-02-05";
String idnumber = "250250199802055250";
String placeoforigin = "贵州";
String sql = " INSERT INTO PERSON_INFO_TABLE(id,name,dateofbirth,idnumber,placeoforigin) "
+ " VALUES(" + id + ", '" + name + "', DATE('" + date + "'), '" + idnumber + "', '" + placeoforigin+ "') ";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
Statement stat = conn.createStatement();
int num = stat.executeUpdate(sql);
System.out.println(num);
conn.close();
}
}
利用Statement执行的SQL语句问题有如下三种:
(1)不能很好的描述出日期的形式;
(2)需要进行SQL语句的拼凑处理,而导致的结果就是:SQL语句的编写与维护困难;
(3)对于一些敏感的字符数据无法进行合理拼凑。
所以现在就可以发现,虽然Statement可以操作数据库,但是其在操作的过程之中,并不是那么的方便,而它最大的弊端在于要进行SQL语句的拼凑。
2 PreparedStatement接口简介
为了解决Statement接口存在的SQL执行问题,所有在java.sql包里面又提供有一个Statement子接口:PreparedStatement,这个接口最大的好处是可以编写正常的SQL(数据不再和SQL语法混合在一起),同时利用占位符的形式,在SQL正常执行完毕后可以进行数据的设置。观察PreparedStatement接口定义:
public interface PreparedStatement extends Statement
如果要想获取PreparedStatement接口的实例,则依然需要通过Connection接口来实现。
(1)创建PreparedStatement接口对象:PreparedStatement prepareStatement(String sql) throws SQLException
由于SQL语句已经在创建PreparedStatement接口对象的时候提供了,所以在执行数据库操作的时候也要更换方法:
(1)数据库更新:int executeUpdate() throws SQLException
(2)数据库查询:ResultSet executeQuery() throws SQLException
范例:利用PreparedStatement解决之前的数据操作问题
package org.lks.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
public class MySQLJDBCDemo {
private static final String DATABASE_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/research_managerment?useSSL=true&serverTimezone=UTC";
private static final String DATABASE_USER = "root";
private static final String DATABASE_PASSWORD = "19990821";
public static void main(String[] args) throws Exception{
int id = 1002;
String name = "zsl";
String date = "1998-02-05";
String idnumber = "250250199802055250";
String placeoforigin = "贵州";
String sql = " INSERT INTO PERSON_INFO_TABLE(id,name,dateofbirth,idnumber,placeoforigin) "
+ " VALUES(?,?,?,?,?)";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
PreparedStatement pstat = conn.prepareStatement(sql);
pstat.setInt(1, id);
pstat.setString(2, name);
pstat.setDate(3, new java.sql.Date(new SimpleDateFormat("yyyy-MM-dd").parse(date).getTime()));
pstat.setString(4, idnumber);
pstat.setString(5, placeoforigin);
int num = pstat.executeUpdate();
System.out.println(num);
conn.close();
}
}
在JDBC里面不管使用的是PreparedStatement设置的日期时间还是使用ResultSet获取的日期时间实际上都是java.util.Date的子类,也就是说现在是如下的对应关系:
3 使用PreparedStatement实现
清楚了使用PreparedStatement实现更新处理之后,那么下面可以使用其实现数据的查询处理操作,由于在开发之中PreparedStatement的使用是最广泛的,下面将列举几个有代表性的查询。
1、查询全部数据
package org.lks.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Date;
public class MySQLJDBCDemo {
private static final String DATABASE_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/research_managerment?useSSL=true&serverTimezone=UTC";
private static final String DATABASE_USER = "root";
private static final String DATABASE_PASSWORD = "19990821";
public static void main(String[] args) throws Exception{
String sql = "select id,name,dateofbirth,idnumber,placeoforigin from person_info_table";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
PreparedStatement pstat = conn.prepareStatement(sql);
ResultSet rs = pstat.executeQuery();
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
Date date = rs.getDate("dateofbirth");
String idnumber = rs.getString("idnumber");
String placeoforigin = rs.getString("placeoforigin");
System.out.println(id + " " + name + " " + date.toString() +
" " + idnumber + " " + placeoforigin);
}
conn.close();
}
}
2、根据id进行数据查询
package org.lks.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Date;
public class MySQLJDBCDemo {
private static final String DATABASE_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/research_managerment?useSSL=true&serverTimezone=UTC";
private static final String DATABASE_USER = "root";
private static final String DATABASE_PASSWORD = "19990821";
public static void main(String[] args) throws Exception{
String sql = "select id,name,dateofbirth,idnumber,placeoforigin from person_info_table where id=?";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
PreparedStatement pstat = conn.prepareStatement(sql);
pstat.setInt(1, 1000);
ResultSet rs = pstat.executeQuery();
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
Date date = rs.getDate("dateofbirth");
String idnumber = rs.getString("idnumber");
String placeoforigin = rs.getString("placeoforigin");
System.out.println(id + " " + name + " " + date.toString() +
" " + idnumber + " " + placeoforigin);
}
conn.close();
}
}
3、在进行全部数据查询的时候如果返回的内容过多则一定会造成内存的大量占用,那么此时可以使用分页的形式实现数据的查询处理(模糊查询)。
package org.lks.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Date;
public class MySQLJDBCDemo {
private static final String DATABASE_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/research_managerment?useSSL=true&serverTimezone=UTC";
private static final String DATABASE_USER = "root";
private static final String DATABASE_PASSWORD = "19990821";
public static void main(String[] args) throws Exception{
int num = 2;
int page = 2;
String sql = "select id,name,dateofbirth,idnumber,placeoforigin from person_info_table limit ?,?";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
PreparedStatement pstat = conn.prepareStatement(sql);
pstat.setInt(1, (page-1) * num);
pstat.setInt(2, num);
ResultSet rs = pstat.executeQuery();
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
Date date = rs.getDate("dateofbirth");
String idnumber = rs.getString("idnumber");
String placeoforigin = rs.getString("placeoforigin");
System.out.println(id + " " + name + " " + date.toString() +
" " + idnumber + " " + placeoforigin);
}
conn.close();
}
}