JDBC連接數據庫步驟:
一、加載驅動(先導入mysql-connector-java-5.1.49.jar 右擊項目 -> BuildPath -> Configure BuildPath->AddExteranl JARs...)
二、連接數據庫
三、使用語句操作數據庫
四、關閉數據庫連接,釋放資源
//驅動
private static String jdbcName = "com.mysql.jdbc.Driver"; /**
*jdbc:mysql://IP 地址:端口號/數據庫名稱
*jdbc 協議:JDBC URL 中的協議總是 jdbc
*子協議:驅動程序名或數據庫連接機制(這種機制可由一個或多個驅動程序支持)的名稱,如 mysql
*子名稱:一種標識數據庫的方法。必須遵循“//主機名:端口/子協議(數據庫名)”的標准 URL 命名約定,如 //localhost:3306/test
/
private static String dbUrl = "jdbc:mysql://localhost:3306/test"; private static String user = "root"; private static String password = "root"; public static void main(String[] args) { Connection conn = null; try { //加載驅動 Class.forName(jdbcName); System.out.println("驅動加載成功");
//DriverManager驅動管理類,主要負責獲取一個數據庫的連接 conn = DriverManager.getConnection(dbUrl, user, password); System.out.println("連接成功"); } catch (ClassNotFoundException e) { e.printStackTrace(); System.err.println("驅動加載失敗"); } catch (SQLException e) { e.printStackTrace(); }finally { try { conn.close();//關閉連接 } catch (SQLException e) { e.printStackTrace(); } } }
工具類
import java.sql.Connection; import java.sql.DriverManager; public class DbUitl { private static String jdbcName = "com.mysql.jdbc.Driver"; private static String dbUrl = "jdbc:mysql://localhost:3306/test"; private static String user = "root"; private static String password = "root"; /** * 獲取數據庫連接 * @return * @throws Exception */ public Connection getCon() throws Exception{ Class.forName(jdbcName); Connection connection = DriverManager.getConnection(dbUrl, user, password); return connection; } /** * 關閉連接 * @param connection * @throws Exception */ public void close(Statement statement,Connection connection) throws Exception{
if(statement != null){
statement.close();
if(connection != null ){
connection.close();
}
}
} }
Statement接口
作用:用於執行靜態 SQL 語句並返回它所生成結果的對象。
intexecuteUpdate(String sql) 執行給定 SQL 語句,該語句可能為 INSERT、UPDATE 或 DELETE 語句,或 者不返回任何內容的 SQL 語句(如 SQLDDL 語句)。 voidclose() 立即釋放此 Statement 對象的數據庫和 JDBC 資源,而不是等待該對象自動關閉時發生此操作
DbUitl dbUitl = new DbUitl(); String sql = "insert into t_book value(null,'java牛逼',888,'B哥',1)"; try { Connection conn = dbUitl.getCon();//獲取數據庫連接 Statement statement = conn.createStatement();//獲取Statement int result = statement.executeUpdate(sql);//可以執行增、刪、改操作 System.out.println("操作結果:"+result+"數據"); dbUitl.close(statement,conn);//關閉statement和conn } catch (Exception e) { e.printStackTrace(); }
PreparedStatement接口
PreparedStatement 是 Statement 的子接口,屬於預處理操作,與直接使用 Statement 不同的是,PreparedStatement 在操作時,是先在數據表中准備好了一條 SQL 語句,但是此 SQL 語句的具體內容暫時不設置,而是之后再進 行設置。 (以后開發一般用 PreparedStatement,不用 Statement)
DbUitl dbUitl = new DbUitl(); String sql = "insert into t_book value(null,?,?,?,?)"; try { Connection conn = dbUitl.getCon();//獲取數據庫連接 PreparedStatement prestmt = conn.prepareStatement(sql);//獲取Statement prestmt.setString(1, "節哀吧"); prestmt.setFloat(2, 2); prestmt.setString(3, "我"); prestmt.setInt(4, 2); int result = prestmt.executeUpdate(); System.out.println("操作結果:"+result+"數據"); dbUitl.close(prestmt,conn);//關閉preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
結果集:ResultSet(光標剛開始位於第一行之前)
當我們查詢數據庫時,返回的是一個二維的結果集,我們這時候需要使用 ResultSet 來遍歷結果集,獲取每一行 的數據。
使用 ResultSet 遍歷查詢結果
booleannext() 將光標從當前位置向前移一行。
String getString(int columnIndex) 以 Java 編程語言中 String 的形式獲取此 ResultSet 對象的當前行中指定列 的值。
String sql = "select * from t_book"; try { Connection conn = dbUitl.getCon();//獲取數據庫連接 PreparedStatement prestmt = conn.prepareStatement(sql);//獲取Statement //ResultSet 光標剛開始位於第一行之前 ResultSet resultSet = prestmt.executeQuery();//返回結果集 while(resultSet.next()){//光標向前移動一行 int id = resultSet.getInt(1);//獲取第一列的值 String bookName = resultSet.getString(2);//獲取第二列的值 float price = resultSet.getFloat(3);//獲取第三列的值 int bookType = resultSet.getInt(5);//獲取第五列的值 System.out.println("id="+id+"bookName="+bookName+"price="+price+"bookType="+bookType); } dbUitl.close(prestmt,conn);//關閉preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
String getString(String columnLabel) 以 Java 編程語言中 String 的形式獲取此 ResultSet 對象的當前行中指 定列的值
String sql = "select * from t_book"; try { Connection conn = dbUitl.getCon();//獲取數據庫連接 PreparedStatement prestmt = conn.prepareStatement(sql);//獲取Statement //ResultSet 光標剛開始位於第一行之前 ResultSet resultSet = prestmt.executeQuery();//返回結果集 while(resultSet.next()){//光標向前移動一行 int id = resultSet.getInt("id");//獲取數據庫字段為id的值 String bookName = resultSet.getString("bookName");//獲取數據庫字段為bookName值 float price = resultSet.getFloat("price"); int bookType = resultSet.getInt("bookTypeId"); System.out.println("id="+id+"bookName="+bookName+"price="+price+"bookType="+bookType); } dbUitl.close(prestmt,conn);//關閉preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
大數據對象處理主要有 CLOB(characterlarge object)和 BLOB(binary large object)兩種類型的字段;在 CLOB 中可以存儲大字符數據對象,比如長篇小說;在 BLOB 中可以存放二進制大數據對象,比如圖片,電影,音樂
處理CLOB(字符大數據對象)
DbUitl dbUitl = new DbUitl(); String sql = "insert into t_book value(null,?,?,?,?,?)"; try { Connection conn = dbUitl.getCon();//獲取數據庫連接 PreparedStatement prestmt = conn.prepareStatement(sql);//獲取Statement prestmt.setString(1, "節哀吧"); prestmt.setFloat(2, 2); prestmt.setString(3, "我"); prestmt.setInt(4, 2); File file = new File("D:\\test\\LICENSE.txt"); InputStream inputStream = new FileInputStream(file); prestmt.setAsciiStream(5, inputStream, file.length());//數據庫字段為longtext int result = prestmt.executeUpdate(); System.out.println("操作結果:"+result+"數據"); dbUitl.close(prestmt,conn);//關閉preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
String sql = "select * from t_book"; try { Connection conn = dbUitl.getCon();//獲取數據庫連接 PreparedStatement prestmt = conn.prepareStatement(sql);//獲取Statement //ResultSet 光標剛開始位於第一行之前 ResultSet resultSet = prestmt.executeQuery();//返回結果集 while(resultSet.next()){//光標向前移動一行 int id = resultSet.getInt("id");//獲取第一列的值 String bookName = resultSet.getString("bookName");//獲取第二列的值 float price = resultSet.getFloat("price");//獲取第三列的值 int bookType = resultSet.getInt("bookTypeId");//獲取第五列的值 Clob c = resultSet.getClob("context");//獲取CLOB String context = null; if(c!=null){ context = c.getSubString(1, (int)c.length()); } System.out.println("id="+id+"bookName="+bookName+"price="+price+"bookType="+bookType+"context="+context); } dbUitl.close(prestmt,conn);//關閉preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
處理BLOB(二進制大數據對象)
File pic = new File("D:\\test\\1.png"); InputStream inputStream2 = new FileInputStream(pic); prestmt.setBinaryStream(6, inputStream2, pic.length());//數據庫類型為longbolb
Blob b = resultSet.getBlob("pic"); if(b!=null){ FileOutputStream fos = new FileOutputStream(new File("d://pic2.png")); fos.write(b.getBytes(1, (int)b.length())); fos.close(); }
CallableStatement 接口:
CallableStatement 主要是調用數據庫中的存儲過程,CallableStatement 也是 Statement 接口的子接口。在使用 CallableStatement 時可以接收存儲過程的返回值。
//存儲過程
DELIMITER && CREATE PROCEDURE pro_getBookNameByid(IN bookId INT,OUT bN VARCHAR(20)) BEGIN SELECT bookName INTO bN FROM t_book WHERE id = bookId; END && DELIMITER ;
//數據庫執行存儲過程
CALL pro_getBookNameByid(1,@bookName);
SELECT @bookName;//查看值
使用 CallableStatement 接口調用存儲過程:
voidregisterOutParameter(int parameterIndex, intsqlType) 按順序位置 parameterIndex 將 OUT 參數注冊為 JDBC 類型 sqlType
Connection con = dbUitl.getCon(); String sql = "{CALL pro_getBookNameByid(?,?)}"; CallableStatement cstmt = con.prepareCall(sql); cstmt.setInt(1, 2);//第一個參數 輸入參數 id cstmt.registerOutParameter(2, Types.VARCHAR); //第二個參數 輸出參數 cstmt.execute(); String bookName = cstmt.getString("bN"); // 獲取返回值 dbUitl.close(cstmt, con);
使用 DatabaseMetaData 獲取數據庫基本信息
DatabaseMetaData 可以得到數據庫的一些基本信息,包括數據庫的名稱、版本,以及得到表的信息。
StringgetDatabaseProductName() 獲取此數據庫產品的名稱。
intgetDriverMajorVersion() 獲取此 JDBC 驅動程序的主版本號。
intgetDriverMinorVersion() 獲取此 JDBC 驅動程序的次版本號。
Connection con = dbUitl.getCon(); DatabaseMetaData dmd = con.getMetaData(); String dbpn = dmd.getDatabaseProductName();//數據庫名稱 System.out.println(dbpn);//mysql System.out.println("數據庫的版本號:"+ dmd.getDatabaseMajorVersion()+//主版本號 "."+ dmd.getDatabaseMinorVersion()//次版本號 );// 數據庫的版本號:5.5
使用 ResultSetMetaData 獲取 ResultSet 對象中的信息
ResultSetMetaData 可獲取關於 ResultSet 對象中列的基本信息;
intgetColumnCount() 返回此 ResultSet 對象中的列數。
StringgetColumnName(int column) 獲取指定列的名稱。
intgetColumnTypeName(int column) 獲取指定列的 SQL 類型名稱
Connection con = dbUitl.getCon(); String sql = "select * from t_book"; PreparedStatement ps = con.prepareStatement(sql); ResultSetMetaData rsmd = ps.getMetaData();//獲取結果集的元數據 int num = rsmd.getColumnCount();//獲取元數據的總列數 for(int i=1;i<num;i++){ System.out.println(rsmd.getColumnName(i)+","+rsmd.getColumnTypeName(i));//獲取每列的列名以及列的sql類型 }
事務:
事務處理在數據庫開發中有着非常重要的作用,所謂事務就是所有的操作要么一起成功,要么一起失敗,
事務 本身具有原子性(Atomicity)、一致性(Consistency)、隔離性或獨立性(Isolation) 、持久性(Durability)4 個特 性,這 4 個特性也被稱為 ACID 特征。
原子性:原子性是事務最小的單元,是不可再分隔的單元,相當於一個個小的數據庫操作,這些操作必須同時 成功,如果一個失敗了,則一切的操作將全部失敗。
一致性:指的是在數據庫操作的前后是完全一致的,保證數據的有效性,如果事務正常操作則系統會維持有效 性,如果事務出現了錯誤,則回到最原始狀態,也要維持其有效性,這樣保證事務開始時和結束時系統處於一 致狀態。
隔離性:多個事務可以同時進行且彼此之間無法訪問,只有當事務完成最終操作時,才可以看到結果;
持久性:事務完成之后,它對於系統的影響是永久性的。該修改即使出現致命的系統故障也將一直保持。
private static DbUitl dbUitl = new DbUitl();
//轉出 public static void outCount(Connection con,String accountName,int account) throws Exception{ String sql = "update t_account set accountBalance = accountBalance - ? where accountName = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, account); ps.setString(2,accountName); ps.executeUpdate(); }
//轉入 public static void inCount(Connection con,String accountName,int account) throws Exception{ String sql = "update t_account set accountBalance = accountBalance + ? where accountName = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, account); ps.setString(2,accountName); ps.executeUpdate(); } public static void main(String[] args) { Connection con = null; try { con = dbUitl.getCon(); System.out.println("開始轉賬"); con.setAutoCommit(false);//取消自動提交 int account = 500; outCount(con, "張三", account); inCount(con, "李四", account); System.out.println("轉賬結束"); } catch (Exception e) { try { con.rollback();//事務回滾 } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { try { con.commit();//事務提交 con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
Connection con = null; Savepoint sp = null;//保存點 try { con = dbUitl.getCon(); System.out.println("開始轉賬"); con.setAutoCommit(false);//取消自動提交 int account = 500; outCount(con, "張三", account); int i = 1/0; sp = con.setSavepoint();//設置保存點 inCount(con, "李四", account); System.out.println("轉賬結束"); } catch (Exception e) { try { con.rollback(sp);//事務回滾 回滾到保存點 轉出成功 轉入不管 } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { try { con.commit();//事務提交 con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }