Java基础(三十二)JDBC(2)连接数据库
一、連接數據庫的過程
連接數據庫的過程:加載數據庫驅動程序,不過只需在第一次訪問數據庫時加載一次,然后在每次訪問數據庫時創建一個Connection實例,然后執行操作數據庫的SQL語句,并返回執行結果,最后在完成此次操作時銷毀前面創建的Connection實例,釋放與數據庫的連接。
1.加載JDBC驅動程序
// 加載數據庫驅動類,加載失敗拋出ClassNotFoundException異常Class.forName(Driver);2.創建數據庫連接
// 創建一個數據庫連接對象,創建失敗會拋出SQLException異常Connection conn = DriverManager.getConnection(Url, User, Password);3.創建一個Statement對象
// 通過Connection示例創建Statement實例Statement statement = conn.createStatement();4.執行SQL語句并獲得查詢結果
// 通過Statement實例執行SQL語句并返回執行結果ResultSet rs = statement.executeQuery("select * from user");5.關閉連接釋放資源
在每次訪問數據庫后,應該按照下面的順序,及時銷毀這些實例,釋放它們占用的所有資源。
rs.close();statement.close();conn.close();?
二、Statement實例的三種類型
Statement接口中,執行executeQuery方法可以返回查詢結果到結果集中,執行executeUpdate方法可以插入、刪除或者修改數據庫記錄,并返回一個int型數值,表示影響數據庫記錄的條數。
Statement實例分為三種類型:Statement實例、(繼承自Statement)PreparedStatement實例和(繼承自PreparedStatement)CallableStatement實例。
(1)Statement實例是最簡單的Statement實例,只能用來執行靜態的SQL語句
ResultSet rs_queue = statement.executeQuery("select * from user");while (rs_queue.next()) {System.out.println(rs_queue.getInt("id") + " " + rs_queue.getString("name") + " " + rs_queue.getString("sex") + " "+ rs_queue.getString("birthday"));}System.out.println(statement.executeUpdate("update user set sex='女' where id=1")); // 打印:1rs_queue.close();
?? ??? ??? ?statement.close()
(2)PreparedStatement實例增加了執行動態SQL語句的功能
String sql = "update user set name = ?, sex = ?, birthday = ?where id =?";PreparedStatement predStatement = conn.prepareStatement(sql);predStatement.setString(1, "loser");predStatement.setString(2, "女");predStatement.setDate(3, new Date(System.currentTimeMillis()));predStatement.setInt(4, 1);System.out.println(predStatement.executeUpdate()); // 打印:1predStatement.close();(3)CallableStatement實例增加了執行數據庫存儲過程的功能
首先在MySQL中創建一個存儲過程并測試:
mysql> select * from user // +----+-------+------+------------+ | id | name | sex | birthday | +----+-------+------+------------+ | 1 | loser | 女 | 2018-08-06 | | 2 | lsl | 男 | 2017-12-12 | | 3 | zgs | 女 | 2016-06-01 | +----+-------+------+------------+ 3 rows in set (0.00 sec)mysql> create procedure proc_count_select_by_sex(IN girl_or_boy VARCHAR(255))-> READS SQL DATA-> BEGIN-> select count(*) from user where sex=girl_or_boy;-> END-> // Query OK, 0 rows affected (0.00 sec)mysql> call proc_count_select_by_sex('女') // +----------+ | count(*) | +----------+ | 2 | +----------+ 1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)然后使用CallableStatement對象調用存儲過程:
String sql = "{call proc_count_select_by_sex(?)}";CallableStatement cablStat = conn.prepareCall(sql);cablStat.setString(1, "女");ResultSet rs = cablStat.executeQuery();while (rs.next()) {System.out.println(rs.getInt(1)); // 打印:2}rs.close();cablStat.close();
?
三、標準JDBC程序設計
package jdbc.jun.iplab;import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;public class JDBC {private static final String Driver = "com.mysql.jdbc.Driver";private static final String Url = "jdbc:mysql://localhost:3306/mysqldb?useSSL=false";private static final String User = "root";private static final String Password = "bjtungirc";static {try {Class.forName(Driver); } catch (ClassNotFoundException e) {e.printStackTrace();}}public static void main(String[] args) {try { // 創建一個數據庫連接對象,創建失敗會拋出SQLException異常Connection conn = DriverManager.getConnection(Url, User, Password);// 通過Connection示例創建Statement實例Statement statement = conn.createStatement();// 通過Statement實例執行SQL語句并返回執行結果ResultSet rs_queue = statement.executeQuery("select * from user");while (rs_queue.next()) {System.out.println(rs_queue.getInt("id") + " " + rs_queue.getString("name") + " " + rs_queue.getString("sex") + " "+ rs_queue.getString("birthday"));}System.out.println(statement.executeUpdate("update user set sex='女' where id=1"));rs_queue.close();statement.close();conn.close();} catch (SQLException e) {e.printStackTrace();} } } JDBC標準代碼設計? 實際工程中使用JDBC的標準寫法
package fileTransfer;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ResourceBundle;public class DBUtils {private static String driverClass;private static String url ;private static String userName;private static String password;private static Connection connection = null;static{//讀取配置文件,加載數據庫相關信息ResourceBundle resourceBundle = ResourceBundle.getBundle("info");driverClass = resourceBundle.getString("driverClass");url = resourceBundle.getString("url");userName = resourceBundle.getString("userName");password = resourceBundle.getString("password");try {Class.forName(driverClass);} catch (Exception e) {System.out.println(e.toString()+"加載驅動失敗!");}}public static Connection getConnection(){try {connection = DriverManager.getConnection(url, userName, password);} catch (SQLException e) {// TODO Auto-generated catch blockSystem.out.println(e.toString()+"數據庫連接失敗!");}return connection;}public static void CloseAll(ResultSet resultSet, PreparedStatement pStatement, Connection connection){if (resultSet!=null) {try {resultSet.close();} catch (SQLException e) {// TODO Auto-generated catch block e.printStackTrace();}}if (pStatement != null) {try {pStatement.close();} catch (SQLException e) {// TODO Auto-generated catch block e.printStackTrace();}}if(connection != null){try {connection.close();} catch (SQLException e) {// TODO Auto-generated catch block e.printStackTrace();}}} } JDBC標準工程寫法?
四、JDBC連接池
? 實際工程中應該考慮下面的問題:建立數據庫連接需要開銷,因為數據庫連接是有限的資源,如果用戶要離開應用一段時間,那么他占用的連接就不應該保持打開狀態;另一方面,每次查詢都獲取連接并在隨后關閉它的代價也是相當高的。
解決上述問題的方法時建立數據庫連接池(pool),這意味著數據庫連接在物理上并為關閉,而是保留在一個隊列中并被反復重用。
連接池的使用對程序員來說是完全透明的,可以通過獲取數據源并調用getConnection方法來得到連接池中的連接。使用完連接后,需要調用close()方法,該方法不再物理上關閉連接,而是只告訴連接池已經使用完該連接,將Connection對象返回到LinkedList對象中。
1.編寫連接池需要實現java.sql.DataSource接口
2.創建LinkedList對象,并創建“最小連接數”個Connection對象并將這些對象添加到LinkedList對象中
3.重寫getConnection方法,使用動態代理技術管理連接池中的Connection對象
4.封裝getConnection()方法和release()方法
示例代碼
- 配置文件jdbc.properties
- 連接池類ConnectionPool
} }
- 封裝的JDBC連接類DBUtils類(包括了getConnection方法和closeAll方法) package connPool.jun.iplab;import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;public class Get_jdbc_conn_from_cPool {private static ConnectionPool cPool = new ConnectionPool();public static Connection getConnection() throws SQLException{return cPool.getConnection();}public static void CloseAll(ResultSet resultSet, PreparedStatement pStatement, Connection connection){if (resultSet!=null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (pStatement != null) {try {pStatement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection != null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}} }
- 測試類 package connPool.jun.iplab;import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;public class CPoolTest {public static void main(String[] args) throws SQLException {// 得到數據庫連接對象Connection conn = DBUtils.getConnection();// 數據庫操作Statement statement = conn.createStatement();ResultSet rs = statement.executeQuery("select * from user where sex='男'");while (rs.next()) {System.out.println(rs.getInt("id") + " " + rs.getString("name") + " " + rs.getString("sex") + " "+ rs.getString("birthday"));}// 執行這條語句時,conn對象執行了close()方法,因此會將conn對象重新添加到LinkedList集合中 DBUtils.CloseAll(rs, statement, conn);} }
- 輸出 2 lsl 男 2017-12-12
4 winner 男 2018-08-07
9 nine 男 2018-08-07
ResultSet對象已關閉
Statement對象已關閉
Connection對象已關閉
?
?
轉載于:https://www.cnblogs.com/BigJunOba/p/9431241.html
總結
以上是生活随笔為你收集整理的Java基础(三十二)JDBC(2)连接数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ACE(Adaptive Communi
- 下一篇: Java线程池理解及用法