1. 建立一個獲取Connection對象和關閉資源的工具類java
在對數據庫進行CRUD(①查詢數據、②數據插入、③數據修改、④數據刪除)操做的時候,每個操做都須要獲取Connection對象,因此咱們就能夠把獲取Connection對象的過程抽離到一個工具類當中,下面是具體代碼。sql
public final class JdbcUtil { private JdbcUtil() { } private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL"; private static String user = "scott"; private static String password = "tiger"; // 經過靜態代碼塊加載驅動類 static { try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError("加載驅動類出錯!!"); } } // 獲取鏈接對象 public static Connection getConnection() throws Exception { Connection connection = null; connection = DriverManager.getConnection(url, user, password); return connection; } // 關閉資源 public static void close(Connection connection, ResultSet rs, Statement statement) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } finally { if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } finally { if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } } } }
我把url,username,password放在了類中,也能夠將這些配置信息放入到配置文件中,通常的作法是放入到配置文件當中,此處就簡單些。將加載驅動類的方法放入到static靜態代碼塊當中,當調用getConnection靜態方法的時候,static靜態代碼塊會先執行,即會先加載驅動類。close()方法就是關閉Statement,Connection,ResultSet對象的資源。數據庫
2. 使用Statement對象和ResultSet對象進行簡單CRUD(增刪改查)操做安全
首先看一下Statement接口的文檔說明:oracle
用於執行靜態SQL語句並返回它所生成的結果的對象。工具
在默認狀況下,同一時間每一個Statement對象在只能打開一個ResultSet對象。所以,若是讀取一個ResultSet對象與讀取另外一個交叉,則這兩個對象必須是由不一樣的Statement對象生成的。若是存在某個語句的打開的當前ResultSet對象,則Statement接口中的全部執行方法都會隱式關閉它。url
Statement的主要做用就是執行SQL語句而且返回它所生產的結果對象。Statement對象是經過Connection對象進行獲取的,經過Connection.createStatement()方法獲取Statement對象。經過執行Statement對象的executeQuery()方法進行查詢SQL,該語句返回單個ResultSet 對象。spa
下面是簡單的代碼示例:code
public void read(String id, String password) { Connection connection = null; // 初始化一個鏈接對象 Statement statement = null; // 初始化一個語句對象 ResultSet resultSet = null; // 初始化一個結果集對象 try { connection = JdbcUtil.getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery("select id, name from student where id = '" + id + "' and password = '" + password + "'"); while (resultSet.next()) { System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name")); } } catch(SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(connection, resultSet, statement); } }
模擬了一個簡單的查詢用戶信息的SQL,傳入id和password對數據庫進行查詢,而後輸出。SQL語句是經過傳入的值拼接而成,因此這樣就很容易被SQL注入。當我傳入的password值爲' or 1 = 1 or '的時候打印出來SQL語句以下:對象
select id, name from student where id = 'rcx' and password = '' or 1 = 1 or ''
所以就能夠查詢到用戶的信息,引發不安全的漏洞。通常帶參數的查詢都須要使用PreparedStatement對象。
3. 使用PreparedStatement對象(即預處理語句對象)和ResultSet對象進行簡單CRUD(增刪改查)操做
首先看一下PreparedStatement接口,它繼承自Statement接口。PreparedStatement對象(即預處理語句對象)表示預編譯的SQL語句。SQL語句被預編譯並存儲在PreparedStatement對象中。而後能夠使用此對象屢次高效地執行該SQL語句。預處理語句對象是Connection對象(即鏈接對象)經過調用prepareStatement(sql)方法來獲取的,傳入的參數是還未預編譯的SQL語句(即原始的SQL語句),可是該SQL語句的特殊之處在於參數部分是用?來代替。2中的SQL語句的例子經過PreparedStatement類實現的代碼以下:
public void read1(String id, String password) { Connection connection = null; PreparedStatement pstmt = null; ResultSet resultSet = null; try { connection = JdbcUtil.getConnection(); // 下面這條SQL語句是預編譯語句類的核心,該SQL語句不是經過傳入的值拼接而成。 String sql = "select id, name from student where id = ? and password = ?"; pstmt = connection.prepareStatement(sql); pstmt.setString(1, id); pstmt.setString(2, password); // 該方法是不帶參數的,不然執行的不是預處理(即預編譯)的SQL語句 resultSet = pstmt.executeQuery(); while (resultSet.next()) { System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name")); } } catch(SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(connection, resultSet, pstmt); } }
由於PreparedStatement對象中包含的是預處理SQL語句,因此能夠有效地防止SQL注入的問題,同時還能夠提升一些效率。
注意:
resultSet = pstmt.executeQuery();
因爲PreparedStatement接口繼承自Statement接口,因此也有executeQuery(sql)帶參數的方法,若是這樣寫的話那麼執行的就是父類接口當中的方法了,則執行的不是預處理的SQL語句。
4. 一些其餘的方法
因爲執行數據查詢的語句是經過調用ResultSet對象的executeQuery()方法來實現的,在插入數據、更新數據、刪除數據的操做是經過調用executeUpdate(SQL)方法來實現的。因此執行給定的SQL語句,該語句可能爲INSERT(插入數據)、UPDATE(修改數據)或DELETE(刪除數據)語句,或者不返回任何內容的SQL語句(如SQL DDL語句)。
ResultSet對象的next()方法:將光標從當前位置向前移一行。ResultSet光標最初位於第一行以前;第一次調用next()方法使第一行成爲當前行;第二次調用使第二行成爲當前行,依此類推。
完整的CRUD代碼:
public class CRUD { public static void main(String[] args) throws SQLException { read(); // create(); // update(); // delete(); } // 數據查詢 static void read() throws SQLException { Connection conn = null; Statement st = null; ResultSet rs = null; try { // 2.創建鏈接,獲取鏈接對象 conn = JdbcUtils.getConnection(); // conn = JdbcUtilsSing.getInstance().getConnection(); // 3.建立語句,此處即SQL語句 st = conn.createStatement(); // 4.執行語句,數據查詢語句 rs = st.executeQuery("select id, name, money, birthday from user"); // 5.處理結果 while (rs.next()) { System.out.println(rs.getObject("id") + "\t" + rs.getObject("name") + "\t" + rs.getObject("birthday") + "\t" + rs.getObject("money")); } } finally { JdbcUtils.free(rs, st, conn); } } // 插入數據 static void create() throws SQLException { Connection conn = null; Statement st = null; ResultSet rs = null; try { // 2.創建鏈接 conn = JdbcUtils.getConnection(); // conn = JdbcUtilsSing.getInstance().getConnection(); // 3.建立語句 st = conn.createStatement(); String sql = "insert into user(name,birthday, money) values ('name1', '1987-01-01', 400) "; // 4.執行語句 int i = st.executeUpdate(sql); System.out.println("i=" + i); } finally { JdbcUtils.free(rs, st, conn); } } // 修改數據 static void update() throws SQLException { Connection conn = null; Statement st = null; ResultSet rs = null; try { // 2.創建鏈接 conn = JdbcUtils.getConnection(); // conn = JdbcUtilsSing.getInstance().getConnection(); // 3.建立語句 st = conn.createStatement(); String sql = "update user set money=money+10 "; // 4.執行語句 int i = st.executeUpdate(sql); System.out.println("i=" + i); } finally { JdbcUtils.free(rs, st, conn); } } // 刪除數據 static void delete() throws SQLException { Connection conn = null; Statement st = null; ResultSet rs = null; try { // 2.創建鏈接 conn = JdbcUtils.getConnection(); // conn = JdbcUtilsSing.getInstance().getConnection(); // 3.建立語句 st = conn.createStatement(); String sql = "delete from user where id>4"; // 4.執行語句 int i = st.executeUpdate(sql); System.out.println("i=" + i); } finally { JdbcUtils.free(rs, st, conn); } } }