db.propertiesjava
注意:若是使用鏈接池,能夠在這個文件中增長對鏈接池的相關設置:sql
# db connection parameters # key=value driver=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@192.168.201.227:1521:orcl user=openlab pwd=open123 # datasource parameters initSize=1 maxSize=1
DBUtil.javaapache
說明:DBUtil是DBTool的升級版,採用了鏈接池來管理鏈接。數組
package util; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import org.apache.commons.dbcp.BasicDataSource; /** * 1.DBUtil是DBTool的升級版 * 2.採用了鏈接池來管理鏈接 */ public class DBUtil { //DBCP鏈接池提供的實現類 private static BasicDataSource ds; static { Properties p = new Properties(); try { //1.讀取參數 p.load(DBUtil.class.getClassLoader() .getResourceAsStream("db.properties")); String driver = p.getProperty("driver"); String url = p.getProperty("url"); String user = p.getProperty("user"); String pwd = p.getProperty("pwd"); String initSize = p.getProperty("initSize"); String maxSize = p.getProperty("maxSize"); //2.建立鏈接池(1次) ds = new BasicDataSource(); //3.向鏈接池設置參數 ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(user); ds.setPassword(pwd); ds.setInitialSize(new Integer(initSize)); ds.setMaxActive(new Integer(maxSize)); } catch (IOException e) { //異常的處理原則: //1.記錄日誌(Log4j) e.printStackTrace(); //2.能解決就解決(看開發規範) //3.解決不了向上拋給調用者 //具體拋出哪一種類型的異常看開發規範 throw new RuntimeException( "加載配置文件失敗", e); } } public static Connection getConnection() throws SQLException { return ds.getConnection(); } /** * 1.目前咱們使用鏈接都是鏈接池建立的 * 2.鏈接池重寫了鏈接對象內部的close() * 3.目前close()內部的邏輯是歸還: * - 清除鏈接對象內部包含的全部數據 * - 將鏈接對象狀態設置爲空閒態 */ public static void close(Connection conn) { if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException( "關閉鏈接失敗", e); } } } }
Test.javaoracle
說明:這個類用於測試DBUtil測試
package jdbc; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.junit.Test; import util.DBUtil; public class TestDay02 { /** * 1.測試DBUtil * 2.執行DQL * 查詢部門ID爲1的員工 */ @Test public void test1() { //假設頁面傳入的查詢條件是 int deptno = 1; Connection conn = null; try { conn = DBUtil.getConnection(); System.out.println(conn); Statement smt = conn.createStatement(); String sql = "select * from emps_lhh " + "where deptno="+deptno; ResultSet rs = smt.executeQuery(sql); while(rs.next()) { System.out.println(rs.getInt("empno")); System.out.println(rs.getString("ename")); } } catch (SQLException e) { e.printStackTrace(); //測試代碼能夠適當簡化異常處理 } finally { DBUtil.close(conn); } } /** * 演示如何使用PS執行DML */ @Test public void test2() { //假設頁面傳入的數據是 String ename = "曹操"; String job = "丞相"; int mgr = 0; Date hiredate = Date.valueOf("2017-01-22"); Double sal = 8000.0; Double comm = 9000.0; int deptno = 3; Connection conn = null; try { conn = DBUtil.getConnection(); //寫sql時條件用?代替 String sql = "insert into emps_lhh values(" + "emps_seq_lhh.nextval," + "?,?,?,?,?,?,?)"; //建立PS並傳入sql,PS會馬上發送此sql PreparedStatement ps = conn.prepareStatement(sql); //先設置條件:給?賦值 //ps.set類型(?的序號,?的值) ps.setString(1, ename); ps.setString(2, job); ps.setInt(3, mgr); ps.setDate(4, hiredate); ps.setDouble(5, sal); ps.setDouble(6, comm); ps.setInt(7, deptno); //發送參數,執行SQL(計劃) ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn); } } /** * 演示如何使用PS執行DQL */ @Test public void test3() { //假設頁面傳入的查詢條件是 int empno = 1; Connection conn = null; try { conn = DBUtil.getConnection(); String sql = "select * from emps_lhh " + "where empno=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, empno); ResultSet rs = ps.executeQuery(); if(rs.next()) { System.out.println(rs.getString("ename")); System.out.println(rs.getString("job")); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn); } } /** * 使用PS執行查詢語句,能夠避免注入攻擊 */ @Test public void test4() { //假設頁面傳入的參數是 String user = "zhangsan"; String pwd = "a' or 'b'='b"; Connection conn = null; try { conn = DBUtil.getConnection(); String sql = "select * from users_lhh " + "where username=? " + "and password=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, user); ps.setString(2, pwd); ResultSet rs = ps.executeQuery(); if(rs.next()) { System.out.println("登陸成功"); } else { System.out.println("帳號或密碼錯誤"); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn); } } }
Test.javaurl
package jdbc; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import org.junit.Test; import util.DBUtil; public class TestDay03 { /** * 演示如何從ResultSetMetaData * 中讀取結果集相關的描述信息. */ @Test public void test1() { //假設頁面傳入的查詢條件是 int empno = 1; Connection conn = null; try { conn = DBUtil.getConnection(); String sql = "select * from emps_lhh " + "where empno=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, empno); ResultSet rs = ps.executeQuery(); //獲取結果集元數據,它是一個對象, //內部封裝了對結果集的描述信息. ResultSetMetaData md = rs.getMetaData(); //多少列 System.out.println(md.getColumnCount()); //第1列的列名 System.out.println(md.getColumnName(1)); //第1列的類型的編號(常量) System.out.println(md.getColumnType(1)); //第1列的類型的名稱 System.out.println(md.getColumnTypeName(1)); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn); } } /** * 模擬轉帳業務. * * 假設此時用戶已經登陸了網銀, * 而且已經輸入了收款方帳號和 * 轉帳的金額,點擊了轉帳. * * 轉帳的步驟: * 1.驗證收款方帳號是否存在(查詢) * 2.驗證付款方餘額是否夠用(查詢) * 3.將付款方餘額-N元(修改) * 4.將收款方餘額+N元(修改) */ @Test public void test2() { //假設用戶輸入的信息以下 //付款方帳號 String payId = "00001"; //收款方帳號 String recId = "00002"; //轉帳的金額 double mny = 1000.0; //轉帳是一個完整的業務流程,必須保證 //它的完整性,即該流程應處於一個事務 //以內,因此建立一個鏈接. Connection conn = null; try { conn = DBUtil.getConnection(); //取消自動提交事務 conn.setAutoCommit(false); //1.查詢收款方帳號並驗證 String sql = "select * from accounts_lhh " + "where id=?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, recId); ResultSet rs = ps.executeQuery(); if(!rs.next()) { throw new SQLException("收款方帳號不存在"); } double recMny = rs.getDouble("money"); //2.查詢付款方餘額並驗證 String sql2 = "select * from accounts_lhh " + "where id=?"; PreparedStatement ps2 = conn.prepareStatement(sql2); ps2.setString(1, payId); ResultSet rs2 = ps2.executeQuery(); double payMny = 0.0; if(rs2.next()) { payMny = rs2.getDouble("money"); if(payMny<mny) { throw new SQLException("餘額不足"); } } //3.修改付款方餘額 String sql3 = "update accounts_lhh set " + "money=? where id=?"; PreparedStatement ps3 = conn.prepareStatement(sql3); ps3.setDouble(1, payMny-mny); ps3.setString(2, payId); ps3.executeUpdate(); Integer.valueOf("斷電了"); //4.修改收款方餘額 String sql4 = "update accounts_lhh set " + "money=? where id=?"; PreparedStatement ps4 = conn.prepareStatement(sql4); ps4.setDouble(1, recMny+mny); ps4.setString(2, recId); ps4.executeUpdate(); //轉帳是一個完整的過程,只須要在 //整個流程完成後,提交一次事務便可. conn.commit(); } catch (Exception e) { e.printStackTrace(); try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { DBUtil.close(conn); } } /** * 批量添加員工(共108個,每批加50個) */ @Test public void test3() { //這是一個完整的業務,只建立 //1個鏈接,提交1次事務 Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); String sql = "insert into emps_lhh values(" + "emps_seq_lhh.nextval," + "?,?,?,?,?,?,?)"; PreparedStatement ps = conn.prepareStatement(sql); for(int i=1;i<=108;i++) { //每次循環都將數據暫存到ps上 ps.setString(1, "好漢"+i); ps.setString(2, "打劫"); ps.setInt(3, 0); ps.setDate(4, Date.valueOf("2017-01-23")); ps.setDouble(5, 6000.0); ps.setDouble(6, 4000.0); ps.setInt(7, 9); ps.addBatch(); //每循環50次發送一次數據 if(i%50==0) { ps.executeBatch(); //清空ps中的數據,以便於 //暫存下一輪的數據 ps.clearBatch(); } } //循環結束後,爲了不有零頭(8), //再單獨批量發送一次數據.因爲這 //是最後一次發送,因此不用清空ps了 ps.executeBatch(); conn.commit(); } catch (SQLException e) { e.printStackTrace(); try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { DBUtil.close(conn); } } /** * 添加部門及員工數據 * 添加員工時須要獲取到部門的ID */ @Test public void test4() { //假設頁面傳入的數據是 //部門 String dname = "財務部"; String loc = "杭州"; //員工 String ename = "郭嘉"; String job = "謀士"; int mgr = 0; Date hiredate = Date.valueOf("2017-01-23"); double sal = 6000.0; double comm = 2000.0; Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); //增長部門 String sql = "insert into depts values(" + "depts_seq.nextval,?,?)"; //參數2是一個數組,聲明須要ps記住 //的字段的名稱,ps在執行SQL時會 //記住這些字段的值. PreparedStatement ps = conn.prepareStatement( sql, new String[]{"deptno"}); ps.setString(1, dname); ps.setString(2, loc); ps.executeUpdate(); //獲取部門ID //返回的結果集中存儲了一條數據, //該行數據包括咱們讓ps記錄的全部字段. ResultSet rs = ps.getGeneratedKeys(); System.out.println("rs"+rs); //rsorg.apache.commons.dbcp.DelegatingResultSet@27efef64 rs.next(); //獲取ps記錄的字段時必須使用序號 int deptno = rs.getInt(1); System.out.println("deptno"+deptno); //deptno 4 //增長員工 String sql2 = "insert into emps values(" + "emps_seq.nextval," + "?,?,?,?,?,?,?)"; PreparedStatement ps2 = conn.prepareStatement(sql2); ps2.setString(1, ename); ps2.setString(2, job); ps2.setInt(3, mgr); ps2.setDate(4, hiredate); ps2.setDouble(5, sal); ps2.setDouble(6, comm); ps2.setInt(7, deptno); ps2.executeUpdate(); conn.commit(); } catch (SQLException e) { e.printStackTrace(); try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { DBUtil.close(conn); } } }