PreparedStatement数据库操作接口
既然java.sql中有Statement接口实现数据库操作,那为什么又要提供有一个PreparedStatement实现数据库操作?
Statement问题分析
以更新操作为例,在Statement中要想执行SQL语句,那么一定要通过字符串实现SQL结构定义,这种定义如果要结合到用户输入的情况下就可能产生问题产生。
分析Statement接口操作问题
String title = "testNews";
String content = "文本内容";
String sql = "INSERT INTO news(nid,title,content) VALUES(" news_seq.nextval " + title + content)"; //输入复杂,维护困难
利用Statement执行的SQL语句有如下三个问题:
- 不能很好的描述日期的形式;
- 需要进行SQL语句的拼凑处理,导致SQL语句编写维护困难;
- 对于一些敏感字符数据无法进行合理拼凑。
所以可以发现虽然Statement可以操作数据库,但是操作过程中并不是十分方便,而最大的弊端在于SQL语句的拼凑。
PreparedStatement接口简介
为了解决Statement接口存在的SQL语句拼凑问题,所以java.sql中提供一个Statement子接口:PreparedStatement,这个接口最大的好处是可以编写正常的SQL(数据不再和SQL语法混合在一起),同时利用占位符的形式,在SQL正常执行完毕后可以进行数据的设置。PreparedStatement接口定义:
public interface PreparedStatement implements Statement
如果想要获取PreparedStatement接口实例,依然需要通过Connection接口来实现。
- 创建PreparedStatement接口对象:
public PreparedStatement prepareStatement(String sql) throws SQLException
由于SQL语句已经在创建PreparedStatement接口对象的时候提供了,所以在执行数据库操作的时候也要更换方法:
- 数据库更新:
public int executeUpdate() throws SQLException
- 数据库查询:
public ResultSet executeQuery() throws SQLException
利用PreparedStatement解决Statement存在的问题
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date
public class Demo{
private static final String DATABASE_DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DATABASE_URL = "jdbc:oracle:thin:@localhost:1521:mldn"
private static final String DATABASE_USER = "test";
private static final String DATABASE_PASSWORD = "test";
public static void main(String[] args) throws Exception{
String title = "testNews";
String content = "文本内容";
String sql = " INSERT INTO news(nid,title,content) "
+ " VALUES(news_seq.nextval,?,?) "; //使用“?”作为占位符
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL,DATABASE_USER,DATABASE_PASSWORD);
PreparedStatement pstmt = conn.prepareStatement(sql);
//在执行具体数据库操作之前需要为占位符设置内容,按照顺序设置
pstmt.setString(1,title);
pstmt.setString(2,content);
// pstmt.setInt(2,test);
// pstmt.setDate(5, new java.sql.Date(date.getTime())); //!!!重要
int count = pstmt.executeUpdate(); //返回影响的行数
conn.close();
}
}
在JDBC中不管使用的是PreparedStatement设置的日期时间,还是使用的ResultSet获取的日期时间实际上都是java.util.Date的子类,也就是说现在是如下的对应关系:
使用PreparedStatement实现数据查询操作
清楚了PreparedStatement实现更新处理之后,那么下面可以使用其实现数据查询处理操作,由于开发中PreparedStatement的使用是最广泛的,下面列举几个代表性的查询:
1 查询全部数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Demo{
private static final String DATABASE_DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DATABASE_URL = "jdbc:oracle:thin:@localhost:1521:mldn"
private static final String DATABASE_USER = "test";
private static final String DATABASE_PASSWORD = "test";
public static void main(String[] args) throws Exception{
// 程序开发中SELECT子句后面必须跟上具体字段名称
String sql = "SELECT nid,title FROM news";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL,DATABASE_USER,DATABASE_PASSWORD);
PreparedStatement pstmt = conn.PreparedStatement();
ResultSet rs = stmt.executeQurey(sql); //执行查询
while(rs.next()){ //数据未完全输出
int nid = rd.getInt(1);
String title = rs.getString(2); //列数2
System.out.println("nid:" + nid + "-" + "Title:" + title);
}
conn.close();
}
}
2 根据NID查询数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Demo{
private static final String DATABASE_DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DATABASE_URL = "jdbc:oracle:thin:@localhost:1521:mldn"
private static final String DATABASE_USER = "test";
private static final String DATABASE_PASSWORD = "test";
public static void main(String[] args) throws Exception{
// 程序开发中SELECT子句后面必须跟上具体字段名称
String sql = "SELECT nid,title FROM news WHERE nid=?";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL,DATABASE_USER,DATABASE_PASSWORD);
PreparedStatement pstmt = conn.PreparedStatement();
pstmt.setInt(1,5); //设置nid数据
ResultSet rs = stmt.executeQurey(sql); //执行查询
while(rs.next()){ //数据未完全输出
int nid = rd.getInt(1);
String title = rs.getString(2); //列数2
System.out.println("nid:" + nid + "-" + "Title:" + title);
}
conn.close();
}
}
进行全部数据查询的时候如果返回的内容过多则一定会造成内存的大量占用,那么此时可以使用分页的形式实现数据的查询处理(模糊)。
3 根据NID查询数据(分页)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Demo{
private static final String DATABASE_DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DATABASE_URL = "jdbc:oracle:thin:@localhost:1521:mldn"
private static final String DATABASE_USER = "test";
private static final String DATABASE_PASSWORD = "test";
public static void main(String[] args) throws Exception{
int currentPage = 1; //当前页
int lineSize = 10; //每页显示数据行
String columu = "title" //模糊查询列
String keyWord = "test"; //查询关键字
// 程序开发中SELECT子句后面必须跟上具体字段名称
String sql = " SELECT * FROM ( "
+ " nid,title FROM news WHERE "+ columu + "LIKE ? AND ROUNUM<=?) temp "
+ " WHERE temp.rn>? ";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL,DATABASE_USER,DATABASE_PASSWORD);
PreparedStatement pstmt = conn.PreparedStatement();
pstmt.setString(1, "%" + keyWord + "%");
pstmt.setInt(2, currentPage * lineSize);
pstmt.setInt(3, (currentPage -1) * lineSize);
ResultSet rs = stmt.executeQurey(sql); //执行查询
while(rs.next()){ //数据未完全输出
int nid = rd.getInt(1);
String title = rs.getString(2); //列数2
System.out.println("nid:" + nid + "-" + "Title:" + title);
}
conn.close();
}
}
4 统计数据查询
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Demo{
private static final String DATABASE_DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DATABASE_URL = "jdbc:oracle:thin:@localhost:1521:mldn"
private static final String DATABASE_USER = "test";
private static final String DATABASE_PASSWORD = "test";
public static void main(String[] args) throws Exception{
String columu = "title" //模糊查询列
String keyWord = "test"; //查询关键字
// 程序开发中SELECT子句后面必须跟上具体字段名称
String sql = " SELECT COUNT(*) FROM news WHERE "+ columu + "LIKE ?";
Connection conn = null;
Class.forName(DATABASE_DRIVER);
conn = DriverManager.getConnection(DATABASE_URL,DATABASE_USER,DATABASE_PASSWORD);
PreparedStatement pstmt = conn.PreparedStatement();
pstmt.setString(1, "%" + keyWord + "%");
ResultSet rs = stmt.executeQurey(sql); //执行查询
if(rs.next()){
long count = rs.getLong(1);
System.out.println(count);
}
conn.close();
}
}
使用COUNT函数做统计查询的时候一定会返回查询结果,没有数据返回0。
本文为Java基础学习系列最后一篇文章