今天,接着上一篇( mysql 數據庫 )的基礎上,我就寫一下 Java 怎樣鏈接數據庫,而且操做數據庫。html
首先,咱們先來準備一下數據庫鏈接的驅動:java
mysql 的 jar 包下載地址:https://dev.mysql.com/downloads/connector/j/mysql
Oracle 的 jar 包下載地址:https://www.oracle.com/technetwork/cn/middleware/goldengate/downloads/index.htmlsql
本文章還用到 c3p0 的數據庫鏈接池數據庫
c3p0 的 jar 包下載地址:https://sourceforge.net/projects/c3p0/apache
接下來,咱們就開始正式瞭解一下什麼是 JDBC ,用 Java 怎樣鏈接數據庫,而且怎樣操做數據庫。編程
JDBC(Java DataBase Connectivity,java數據庫鏈接)是一種用於執行SQL語句的Java API,能夠爲多種關係數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基準,據此能夠構建更高級的工具和接口,使數據庫開發人員可以編寫數據庫應用程序。服務器
咱們安裝好數據庫以後,咱們的應用程序也是不能直接使用數據庫的,必需要經過相應的數據庫驅動程序,經過驅動程序去和數據庫打交道。其實也就是數據庫廠商的JDBC接口實現,即對Connection等接口的實現類的jar文件。oracle
Driver接口由數據庫廠家提供,做爲java開發人員,只須要使用Driver接口就能夠了。在編程中要鏈接數據庫,必須先裝載特定廠商的數據庫驅動程序,不一樣的數據庫有不一樣的裝載方法。如:工具
裝載MySql驅動:Class.forName("com.mysql.jdbc.Driver");
裝載Oracle驅動:Class.forName("oracle.jdbc.driver.OracleDriver");
Connection與特定數據庫的鏈接(會話),在鏈接上下文中執行sql語句並返回結果。DriverManager.getConnection(url, user, password)方法創建在JDBC URL中定義的數據庫Connection鏈接上。
鏈接MySql數據庫:Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
鏈接Oracle數據庫:Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password");
鏈接SqlServer數據庫:Connection conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://host:port; DatabaseName=database", "user", "password");
經常使用方法:
使用JDBC的步驟
加載JDBC驅動程序 → 創建數據庫鏈接Connection → 建立執行SQL的語句Statement → 處理執行結果ResultSet → 釋放資源
經過初始化驅動類com.mysql.jdbc.Driver,該類就在 mysql-connector-java-5.0.8-bin.jar中。若是你使用的是oracle數據庫那麼該驅動類將不一樣。
//加載數據庫驅動程序(對應的 Driver 實現類中有註冊驅動的靜態代碼塊.) String driver ="com.mysql.jdbc.Driver"; Class.forName(driver);
//經過 DriverManager 的 getConnection() 方法獲取數據庫鏈接. Connection conn = DriverManager.getConnection(url,user,password);
這裏須要提供:url包括如下(jdbc:mysql://ip地址:端口號/須要鏈接的數據庫名字),例如:jdbc:mysql://localhost:3306/db_database05
數據庫所處於的ip:127.0.0.1 (這裏是本機,若是鏈接其餘電腦上的數據庫,請改變該ip)
數據庫的端口號: 3306 (mysql專用端口號)
數據庫名稱: (根據你本身數據庫中的名稱填寫)
數據庫鏈接的用戶名:user
數據庫的登陸密碼:password
/* * 數據庫鏈接工具類 */ package com.hzc.util; import java.sql.Connection; import java.sql.DriverManager; public class DataBaseUtil { /** * 獲取數據庫鏈接 * @return Connection 對象 */ public static Connection getConnection(){ Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/db_database05"; conn = DriverManager.getConnection(url,user,password); //這裏的user和password根據本身的數據庫登陸和密碼填寫 } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 關閉數據庫鏈接 * @param conn Connection 對象 */ public static void closeConnection(Connection conn){ //判斷 conn 是否爲空 if(conn != null){ try { conn.close(); //關閉數據庫鏈接 } catch (Exception e) { e.printStackTrace(); } } } }
這裏在提供 c3p0 數據庫鏈接池的方法
package jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; /* * 操做JDBC的工具類,其中封裝了一些工具方法 */ public class JDBCTools { private static DataSource dataSource = null; //數據庫鏈接池應只初始化一次 static{ dataSource = new ComboPooledDataSource("helloc3p0"); } //數據庫鏈接:經過讀取配置文件從數據庫服務器獲取一個鏈接 public static Connection getConnection() throws Exception{ return dataSource.getConnection(); } //關閉 ResultSet、Statement 和 Connection public static void release(ResultSet rs,Statement statement,Connection conn){ if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(statement != null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } //數據庫鏈接池的 Connection 對象進行 close 時 //並非真的進行關閉, 而是把該數據庫鏈接會歸還到數據庫鏈接池中. if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /* * 處理數據庫的事務 */ //提交事務 public static void commit(Connection conn){ if(conn != null){ try { conn.commit(); } catch (SQLException e) { e.printStackTrace(); } } } //回滾事務 public static void rollback(Connection conn){ if(conn != null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } } //開始事務 public static void beginTx(Connection conn){ if(conn != null){ try { conn.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } } }
C3P0 要在 src 目錄下配置:建立一個名爲 c3p0-config.xml ,而且記住要導入 c3p0 的 jar 包。
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <named-config name="helloc3p0"> <!-- 指定鏈接數據源的基本屬性 --> <property name="user">登陸名</property> <property name="password">密碼</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <!-- 若數據庫中鏈接數不足時, 一次向數據庫服務器申請多少個鏈接 --> <property name="acquireIncrement">5</property> <!-- 初始化數據庫鏈接池時鏈接的數量 --> <property name="initialPoolSize">5</property> <!-- 數據庫鏈接池中的最小的數據庫鏈接數 --> <property name="minPoolSize">5</property> <!-- 數據庫鏈接池中的最大的數據庫鏈接數 --> <property name="maxPoolSize">10</property> <!-- C3P0 數據庫鏈接池能夠維護的 Statement 的個數 --> <property name="maxStatements">20</property> <!-- 每一個鏈接同時可使用的 Statement 對象的個數 --> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>
用於執行靜態SQL語句並返回它所生成結果的對象。
三種Statement類:
經常使用Statement方法:
ResultSet提供檢索不一樣類型字段的方法,經常使用的有:
ResultSet還提供了對結果集進行滾動的方法:
使用後依次關閉對象及鏈接:ResultSet → Statement → Connection
這裏就直接提供數據庫通用的查詢方法,本身寫成一個公用類,須要用查詢方法的時候,就能夠繼承它,調用裏面的方法。
package jdbc; /* * JDBC的工具方法 */ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; public class Dao { // 執行 SQL 語句,使用 PreparedStatement public void update(String sql, Object... args) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, ps, conn); } } // 執行SQL的方法,使用 Statement:insert、update、delete,而不包含select public void update(String sql) { Connection conn = null; Statement st = null; try { conn = JDBCTools.getConnection(); st = conn.createStatement(); st.executeUpdate(sql); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, st, conn); } } // 查詢一條記錄,返回對應的對象 public <T> T get(Class<T> clazz, String sql, Object... args)throws Exception { List<T> result = getForList(clazz, sql, args); if (result.size() > 0) { return result.get(0); } return null; } /* * 傳入 SQL 語句和 Class 對象,返回 SQL 語句查詢的記錄對應的 Class 類的對象的集合 * * @param clazz: 對象的類型 * * @param sql: SQL 語句 * * @param args: 填充 SQL 語句的佔位符的可變參數 * * @return */ public <T> List<T> getForList(Class<T> clazz, String sql, Object... args)throws Exception { List<T> list = new ArrayList<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 一、獲得結果集 conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); // 二、處理結果集,獲得 Map 的 List, 其中一個 Map 對象就是一條記錄. Map 的 key 爲 rs 中列的別名, // Map 的 value 爲列的值 List<Map<String, Object>> values = handleResultSetToMapList(rs); // 三、把 Map 的 List 轉爲 clazz 對應的 List, 其中 Map 的 key 即爲 clazz 對應的對象的 // propertyName, // 而 Map 的 value 即爲 clazz 對應的對象的 propertyValue list = transfterMapListToBeanList(clazz, values); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } return list; } // 把 Map 的 List 轉爲 clazz 對應的 List public <T> List<T> transfterMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values)throws Exception { List<T> result = new ArrayList<>(); T bean = null; if (values.size() > 0) { for (Map<String, Object> m : values) { bean = clazz.newInstance(); for (Map.Entry<String, Object> entry : m.entrySet()) { String propertyName = entry.getKey(); Object value = entry.getValue(); BeanUtils.setProperty(bean, propertyName, value); } // 把 Object 對象放入到 list 中 result.add(bean); } } return result; } /** * 處理結果集, 獲得 Map 的一個 List, 其中一個 Map 對象對應一條記 * * @param resultSet * @return * @throws SQLException */ public List<Map<String, Object>> handleResultSetToMapList(ResultSet rs) throws Exception { // 準備一個 List<Map<String, Object>>:鍵: 存放列的別名, 值: 存放列的值. 其中一個 Map // 對象對應着一條記錄 List<Map<String, Object>> values = new ArrayList<>(); List<String> columnLabels = getColumnLabels(rs); Map<String, Object> map = null; // 處理 ResultSet, 使用 while 循環 while (rs.next()) { map = new HashMap<>(); for (String columnLabel : columnLabels) { Object value = rs.getObject(columnLabel); map.put(columnLabel, value); } // 把一條記錄的一個 Map 對象放入 List 中 values.add(map); } return values; } /** * 獲取結果集的 ColumnLabel 對應的 List * * @param rs * @return * @throws SQLException */ private List<String> getColumnLabels(ResultSet rs) throws Exception { List<String> labels = new ArrayList<>(); ResultSetMetaData rsmd = rs.getMetaData(); for (int i = 0; i < rsmd.getColumnCount(); i++) { labels.add(rsmd.getColumnLabel(i + 1)); } return labels; } // 返回某條記錄的某一個字段的值 或 一個統計的值(一共有多少條記錄等.) @SuppressWarnings("unchecked") public <E> E getForValue(String sql, Object... args) { // 1. 獲得結果集: 該結果集應該只有一行, 且只有一列 Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 1. 獲得結果集 conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); if (rs.next()) { return (E) rs.getObject(1); } } catch (Exception ex) { ex.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } // 2. 取得結果 return null; } }
掌握好 JDBC 的鏈接,Java 寫不少項目都要與數據庫打交道。
本身寫的不是專業,但願你們提一下意見。本身也是在學習 Java 的小白。寫一下博客記錄一下本身的學習狀況。寫一下博客,能瞭解本身學習的水平。