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();
}
}