Transaction 其實指的一組操做,裏面包含許多個單一的邏輯。只要有一個邏輯沒有執行成功,那麼都算失敗。 全部的數據都回歸到最初的狀態(回滾)java
爲了確保邏輯的成功。 例子: 銀行的轉帳。mysql
開啓事務程序員
start transaction;web
提交或者回滾事務sql
commit; 提交事務, 數據將會寫到磁盤上的數據庫 rollback ; 數據回滾,回到最初的狀態。數據庫
關閉自動提交功能。apache
代碼裏面的事務,主要是針對鏈接來的。編程
經過conn.setAutoCommit(false )來關閉自動提交的設置。數組
提交事務 conn.commit();tomcat
回滾事務 conn.rollback();
@Test public void testTransaction(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); //鏈接,事務默認就是自動提交的。 關閉自動提交。 conn.setAutoCommit(false); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣錢, 扣ID爲1 的100塊錢 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); int a = 10 /0 ; //加錢, 給ID爲2 加100塊錢 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); //成功: 提交事務。 conn.commit(); } catch (SQLException e) { try { //事變: 回滾事務 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } }
指的是 事務中包含的邏輯,不可分割。
指的是 事務執行先後。數據完整性
指的是 事務在執行期間不該該受到其餘事務的影響
指的是 事務執行成功,那麼數據應該持久保存到磁盤上。
不考慮隔離級別設置,那麼會出現如下問題。
髒讀 不可重讀讀 幻讀.
* 髒讀 > 一個事務讀到另一個事務還未提交的數據 * 不可重複讀 > 一個事務讀到了另一個事務提交的數據 ,形成了先後兩次查詢結果不一致。
設置A窗口的隔離級別爲 讀未提交
兩個窗口都分別開啓事務
丟失更新
這個隔離級別可以屏蔽 髒讀的現象, 可是引起了另外一個問題 ,不可重複讀。
若是有一個鏈接的隔離級別設置爲了串行化 ,那麼誰先打開了事務, 誰就有了先執行的權利, 誰後打開事務,誰就只能得着,等前面的那個事務,提交或者回滾後,才能執行。 可是這種隔離級別通常比較少用。 容易形成性能上的問題。 效率比較低。
讀未提交 > 讀已提交 > 可重複讀 > 可串行化
可串行化 > 可重複讀 > 讀已提交 > 讀未提交
在代碼裏面會使用事務
conn.setAutoCommit(false); conn.commit(); conn.rollback();
事務只是針對鏈接鏈接對象,若是再開一個鏈接對象,那麼那是默認的提交。
事務是會自動提交的。
讀 髒讀 一個事務讀到了另外一個事務未提交的數據 不可重複讀 一個事務讀到了另外一個事務已提交的數據,形成先後兩次查詢結果不一致 幻讀 一個事務讀到了另外一個事務insert的數據 ,形成先後查詢結果不一致 。 寫 丟失更新。
讀未提交
引起問題: 髒讀
讀已提交
解決: 髒讀 , 引起: 不可重複讀
可重複讀
解決: 髒讀 、 不可重複讀 , 未解決: 幻讀
可串行化
解決: 髒讀、 不可重複讀 、 幻讀。
mySql 默認的隔離級別是 可重複讀
Oracle 默認的隔離級別是 讀已提交
能夠在查詢的時候,加入 for update
要求程序員本身控制。
- 數據庫的鏈接對象建立工做,比較消耗性能。
2.一開始如今內存中開闢一塊空間(集合) , 一開先往池子裏面放置 多個鏈接對象。 後面須要鏈接的話,直接從池子裏面去。不要去本身建立鏈接了。 使用完畢, 要記得歸還鏈接。確保鏈接對象能循環利用。
代碼實現
出現的問題:
須要額外記住 addBack方法
單例。
沒法面向接口編程。
UserDao dao = new UserDaoImpl(); dao.insert();
DataSource dataSource = new MyDataSource();
由於接口裏面沒有定義addBack方法。
怎麼解決? 以addBack 爲切入點。
因爲多了一個addBack 方法,因此使用這個鏈接池的地方,須要額外記住這個方法,而且還不能面向接口編程。
咱們打算修改接口中的那個close方法。 原來的Connection對象的close方法,是真的關閉鏈接。 打算修改這個close方法,之後在調用close, 並非真的關閉,而是歸還鏈接對象。
原有的方法邏輯,不是咱們想要的。 想修改本身的邏輯
直接改源碼 沒法實現。
繼承, 必須得知道這個接口的具體實現是誰。
使用裝飾者模式。
導入jar文件
不使用配置文件:
public void testDBCP01(){ Connection conn = null; PreparedStatement ps = null; try { //1. 構建數據源對象 BasicDataSource dataSource = new BasicDataSource(); //連的是什麼類型的數據庫, 訪問的是哪一個數據庫 , 用戶名, 密碼。。 //jdbc:mysql://localhost/bank 主協議:子協議 ://本地/數據庫 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost/bank"); dataSource.setUsername("root"); dataSource.setPassword("root"); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admin"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } }
使用配置文件方式:
Connection conn = null; PreparedStatement ps = null; try { BasicDataSourceFactory factory = new BasicDataSourceFactory(); Properties properties = new Properties(); InputStream is = new FileInputStream("src//dbcpconfig.properties"); properties.load(is); DataSource dataSource = factory.createDataSource(properties); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "liangchaowei"); ps.setInt(2, 100); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); }
C3P0
拷貝jar文件 到 lib目錄
Connection conn = null; PreparedStatement ps = null; try { //1. 建立datasource ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 設置鏈接數據的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘記了---> 去之前的代碼 ---> jdbc的文檔 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); }
//默認會找 xml 中的 default-config 分支。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 設置鏈接數據的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘記了---> 去之前的代碼 ---> jdbc的文檔 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200);
//dbutils 只是幫咱們簡化了CRUD 的代碼, 可是鏈接的建立以及獲取工做。 不在他的考慮範圍 QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //增長 //queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000); //刪除 //queryRunner.update("delete from account where id = ?", 5); //更新 //queryRunner.update("update account set money = ? where id = ?", 10000000 , 6);
直接new接口的匿名實現類
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>(){ @Override public Account handle(ResultSet rs) throws SQLException { Account account = new Account(); while(rs.next()){ String name = rs.getString("name"); int money = rs.getInt("money"); account.setName(name); account.setMoney(money); } return account; } }, 6); System.out.println(account.toString());
直接使用框架已經寫好的實現類。
查詢單個對象
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //查詢單個對象 Account account = queryRunner.query("select * from account where id = ?", new BeanHandler(Account.class), 8);
查詢多個對象
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); Listlist = queryRunner.query("select * from account ", new BeanListHandler(Account.class));
如下兩個是使用頻率最高的
BeanHandler, 查詢到的單個數據封裝成一個對象 BeanListHandler, 查詢到的多個數據封裝 成一個List<對象>
ArrayHandler, 查詢到的單個數據封裝成一個數組 ArrayListHandler, 查詢到的多個數據封裝成一個集合 ,集合裏面的元素是數組。 MapHandler, 查詢到的單個數據封裝成一個map MapListHandler,查詢到的多個數據封裝成一個集合 ,集合裏面的元素是map。
ColumnListHandler KeyedHandler ScalarHandler
使用命令行演示 使用代碼演示
髒讀、
不可重複讀、
幻讀 丟失更新
悲觀鎖 樂觀鎖 4個隔離級別 讀未提交 讀已提交 可重複讀 可串行化
DBCP
不使用配置
使用配置
C3P0
不使用配置
使用配置 (必須掌握)
自定義鏈接池
裝飾者模式
簡化了咱們的CRUD , 裏面定義了通用的CRUD方法。
queryRunner.update(); queryRunner.query
driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost/bank name=root password=root
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- default-config 默認的配置, --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost/bank</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!-- This app is massive! --> <named-config name="oracle"> <property name="acquireIncrement">50</property> <property name="initialPoolSize">100</property> <property name="minPoolSize">50</property> <property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property> <!-- he's important, but there's only one of him --> <user-overrides user="master-of-the-universe"> <property name="acquireIncrement">1</property> <property name="initialPoolSize">1</property> <property name="minPoolSize">1</property> <property name="maxPoolSize">5</property> <property name="maxStatementsPerConnection">50</property> </user-overrides> </named-config> </c3p0-config>
#鏈接設置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/bank username=root password=root #<!-- 初始化鏈接 --> initialSize=10 #最大鏈接數量 maxActive=50 #<!-- 最大空閒鏈接 --> maxIdle=20 #<!-- 最小空閒鏈接 --> minIdle=5 #<!-- 超時等待時間以毫秒爲單位 6000毫秒/1000等於60秒 --> maxWait=60000 #JDBC驅動創建鏈接時附帶的鏈接屬性屬性的格式必須爲這樣:[屬性名=property;] #注意:"user" 與 "password" 兩個屬性會被明確地傳遞,所以這裏不須要包含他們。 connectionProperties=useUnicode=true;characterEncoding=gbk #指定由鏈接池所建立的鏈接的自動提交(auto-commit)狀態。 defaultAutoCommit=true #driver default 指定由鏈接池所建立的鏈接的事務級別(TransactionIsolation)。 #可用值爲下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
c3p0
package com.itheima.c3p0; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.dbcp.BasicDataSource; import org.junit.Test; import com.itheima.uitl.JDBCUtil; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Demo { @Test public void testC3P0 (){ Connection conn = null; PreparedStatement ps = null; try { //1. 建立datasource // ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle"); //默認會找 xml 中的 default-config 分支。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); System.out.println(dataSource.hashCode() ); ComboPooledDataSource dataSource2 = new ComboPooledDataSource(); System.out.println(dataSource2.hashCode()+"-------"); //2. 設置鏈接數據的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘記了---> 去之前的代碼 ---> jdbc的文檔 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.c3p0; import java.sql.Connection; import java.sql.PreparedStatement; import org.junit.Test; import com.itheima.uitl.JDBCUtil; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Demo02 { @Test public void testC3P0(){ Connection conn = null; PreparedStatement ps = null; try { //就new了一個對象。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "wangwu2"); ps.setInt(2, 2600); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.c3p0; import java.sql.Connection; import java.sql.SQLException; import com.itheima.uitl.JDBCUtil; import com.itheima.uitl.JDBCUtil02; public class Test { public static void main(String[] args) { try { Connection conn = JDBCUtil02.getConn(); conn.prepareStatement(null); } catch (SQLException e) { e.printStackTrace(); } } }
package com.itheima.dbcp; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.dbcp.BasicDataSource; import org.junit.Test; import com.itheima.uitl.JDBCUtil; public class DBCPDemo { @Test public void testDBCP01(){ Connection conn = null; PreparedStatement ps = null; try { //1. 構建數據源對象 BasicDataSource dataSource = new BasicDataSource(); //連的是什麼類型的數據庫, 訪問的是哪一個數據庫 , 用戶名, 密碼。。 // jdbc:mysql://localhost/bank 主協議:子協議 ://本地/數據庫 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost/bank"); dataSource.setUsername("root"); dataSource.setPassword("root"); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admin"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.dbcp; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Properties; import java.util.ResourceBundle; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import org.junit.Test; import com.itheima.uitl.JDBCUtil; public class DBCPDemo02 { @Test public void testDBCP02(){ /*BasicDataSource dataSource = new BasicDataSource(); //不知道這行能不能實現。 dataSource.setConnectionProperties("dbcpconfig.properties");*/ //ResourceBundle bundler = ResourceBundle.getBundle(baseName); Connection conn = null; PreparedStatement ps = null; try { BasicDataSourceFactory factory = new BasicDataSourceFactory(); Properties properties = new Properties(); // InputStream is = new FileInputStream("src//dbcpconfig.properties"); InputStream is = getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties"); properties.load(is); DataSource dataSource = factory.createDataSource(properties); //2. 獲得鏈接對象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "liangchaowei22"); ps.setInt(2, 200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.dbutils; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.junit.Test; import com.itheima.domain.Account; import com.mchange.v2.c3p0.ComboPooledDataSource; /* //針對增長 、 刪除 、 修改 queryRunner.update(sql) //針對查詢 queryRunner.query(sql, rsh);*/ public class TestDBUtils { @Test public void testInsert() throws SQLException, InstantiationException, IllegalAccessException{ // ComboPooledDataSource dataSource = new ComboPooledDataSource(); //dbutils 只是幫咱們簡化了CRUD 的代碼, 可是鏈接的建立以及獲取工做。 不在他的考慮範圍 QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //增長 //queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000); //刪除 // queryRunner.update("delete from account where id = ?", 5); //更新 //queryRunner.update("update account set money = ? where id = ?", 10000000 , 6); //去執行查詢,查詢到的數據仍是在哪一個result裏面。 而後調用下面的handle方法,由用戶手動去封裝。 /*Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>(){ @Override public Account handle(ResultSet rs) throws SQLException { Account account = new Account(); while(rs.next()){ String name = rs.getString("name"); int money = rs.getInt("money"); account.setName(name); account.setMoney(money); } return account; } }, 6); System.out.println(account.toString()); */ // 經過類的字節碼獲得該類的實例 /* Account a = new Account(); //建立一個類的實例。 Account a1= Account.class.newInstance(); */ //查詢單個對象 Account account = queryRunner.query("select * from account where id = ?", new BeanHandler<Account>(Account.class), 8); System.out.println(account.toString()); /*List<Account> list = queryRunner.query("select * from account ", new BeanListHandler<Account>(Account.class)); for (Account account : list) { System.out.println(account.toString()); }*/ } }
package com.itheima.domain; public class Account { private String name02; private int money; public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public String getName02() { return name02; } public void setName02(String name02) { this.name02 = name02; } @Override public String toString() { return "Account [name02=" + name02 + ", money=" + money + "]"; } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一個屬性配置對象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用類加載器,去讀取src底下的資源文件。 後面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //導入輸入流。 properties.load(is); //讀取屬性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取鏈接對象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //靜態代碼塊 ---> 類加載了,就執行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 創建鏈接 參數一: 協議 + 訪問的數據庫 , 參數二: 用戶名 , 參數三: 密碼。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 釋放資源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JDBCUtil02 { static ComboPooledDataSource dataSource = null; static{ dataSource = new ComboPooledDataSource(); } /** * 獲取鏈接對象 * @return * @throws SQLException */ public static Connection getConn() throws SQLException{ return dataSource.getConnection(); } /** * 釋放資源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.uitl; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.sql.DataSource; /** * 這是一個數據庫鏈接池 * 一開始先往池子裏面放10個鏈接 * * 1. 開始建立10個鏈接。 * * 2. 來的程序經過getConnection獲取鏈接 * * 3. 用完以後,使用addBack 歸還鏈接。 * * 4. 擴容。 * * * 問題: * * 1. sun公司針對數據庫鏈接池定義的一套規範。 * * 1. 須要額外記住 addBack方法 * * 2. 單例。 * * 3. 沒法面向接口編程。 * * UserDao dao = new UserDaoImpl(); * dao.insert(); * * * DataSource dataSource = new MyDataSource(); * * 由於接口裏面沒有定義addBack方法。 * * 4. 怎麼解決? * */ public class MyDataSource implements DataSource { List <Connection> list = new ArrayList<Connection>(); public MyDataSource() { for (int i = 0; i < 10; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } // 該鏈接池對外公佈的獲取鏈接的方法 @Override public Connection getConnection() throws SQLException { //來拿鏈接的時候,先看看,池子裏面還有沒有。 if(list.size() == 0 ){ for (int i = 0; i < 5; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } //remove(0) ---> 移除第一個。 移除的是集合中的第一個。 移除的是開始的那個元素 Connection conn = list.remove(0); return conn; } /** * 用完以後,記得歸還。 * @param conn */ public void addBack(Connection conn){ list.add(conn); } //---------------------------- @Override public PrintWriter getLogWriter() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setLogWriter(PrintWriter out) throws SQLException { // TODO Auto-generated method stub } @Override public void setLoginTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getLoginTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { // TODO Auto-generated method stub return null; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Connection getConnection(String username, String password) throws SQLException { // TODO Auto-generated method stub return null; } }
package com.itheima.uitl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; public class TestPool { @Test public void testPool(){ Connection conn = null; PreparedStatement ps = null; MyDataSource dataSource = new MyDataSource(); try { conn = dataSource.getConnection(); String sql = "insert into account values (null , 'xilali' , 10)"; ps = conn.prepareStatement(sql); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } //歸還鏈接 //conn.close(); dataSource.addBack(conn); //JDBCUtil.release(conn, st, rs); } } }
package com.itheima.uitl; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; public class ConnectionWrap implements Connection{ Connection connection = null; List <Connection> list ; public ConnectionWrap(Connection connection , List <Connection> list) { super(); this.connection = connection; this.list = list; } @Override public void close() throws SQLException { //connection.close(); System.out.println("有人來歸還鏈接對象了。 歸還以前,池子裏面是:"+list.size()); list.add(connection); System.out.println("有人來歸還鏈接對象了。 歸還以後...,池子裏面是:"+list.size()); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return connection.prepareStatement(sql); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Statement createStatement() throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql) throws SQLException { // TODO Auto-generated method stub return null; } @Override public String nativeSQL(String sql) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setAutoCommit(boolean autoCommit) throws SQLException { // TODO Auto-generated method stub } @Override public boolean getAutoCommit() throws SQLException { // TODO Auto-generated method stub return false; } @Override public void commit() throws SQLException { // TODO Auto-generated method stub } @Override public void rollback() throws SQLException { // TODO Auto-generated method stub } @Override public boolean isClosed() throws SQLException { // TODO Auto-generated method stub return false; } @Override public DatabaseMetaData getMetaData() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setReadOnly(boolean readOnly) throws SQLException { // TODO Auto-generated method stub } @Override public boolean isReadOnly() throws SQLException { // TODO Auto-generated method stub return false; } @Override public void setCatalog(String catalog) throws SQLException { // TODO Auto-generated method stub } @Override public String getCatalog() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setTransactionIsolation(int level) throws SQLException { // TODO Auto-generated method stub } @Override public int getTransactionIsolation() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public SQLWarning getWarnings() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void clearWarnings() throws SQLException { // TODO Auto-generated method stub } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Map<String, Class<?>> getTypeMap() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException { // TODO Auto-generated method stub } @Override public void setHoldability(int holdability) throws SQLException { // TODO Auto-generated method stub } @Override public int getHoldability() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Savepoint setSavepoint() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Savepoint setSavepoint(String name) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void rollback(Savepoint savepoint) throws SQLException { // TODO Auto-generated method stub } @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { // TODO Auto-generated method stub } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Clob createClob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Blob createBlob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public NClob createNClob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public SQLXML createSQLXML() throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isValid(int timeout) throws SQLException { // TODO Auto-generated method stub return false; } @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { // TODO Auto-generated method stub } @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { // TODO Auto-generated method stub } @Override public String getClientInfo(String name) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Properties getClientInfo() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setSchema(String schema) throws SQLException { // TODO Auto-generated method stub } @Override public String getSchema() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void abort(Executor executor) throws SQLException { // TODO Auto-generated method stub } @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getNetworkTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一個屬性配置對象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用類加載器,去讀取src底下的資源文件。 後面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //導入輸入流。 properties.load(is); //讀取屬性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取鏈接對象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //靜態代碼塊 ---> 類加載了,就執行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 創建鏈接 參數一: 協議 + 訪問的數據庫 , 參數二: 用戶名 , 參數三: 密碼。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 釋放資源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.uitl; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.sql.DataSource; /** * 這是一個數據庫鏈接池 * 一開始先往池子裏面放10個鏈接 * * 1. 開始建立10個鏈接。 * * 2. 來的程序經過getConnection獲取鏈接 * * 3. 用完以後,使用addBack 歸還鏈接。 * * 4. 擴容。 * * * 問題: * * 1. sun公司針對數據庫鏈接池定義的一套規範。 * * 1. 須要額外記住 addBack方法 * * 2. 單例。 * * 3. 沒法面向接口編程。 * * UserDao dao = new UserDaoImpl(); * dao.insert(); * * * DataSource dataSource = new MyDataSource(); * * 由於接口裏面沒有定義addBack方法。 * * 4. 怎麼解決? * */ public class MyDataSource implements DataSource { List <Connection> list = new ArrayList<Connection>(); public MyDataSource() { for (int i = 0; i < 10; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } // 該鏈接池對外公佈的獲取鏈接的方法 @Override public Connection getConnection() throws SQLException { //來拿鏈接的時候,先看看,池子裏面還有沒有。 if(list.size() == 0 ){ for (int i = 0; i < 5; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } //remove(0) ---> 移除第一個。 移除的是集合中的第一個。 移除的是開始的那個元素 Connection conn = list.remove(0); //在把這個對象拋出去的時候, 對這個對象進行包裝。 Connection connection = new ConnectionWrap(conn, list); return connection; } /** * 用完以後,記得歸還。 * @param conn */ public void addBack(Connection conn){ list.add(conn); } //---------------------------- @Override public PrintWriter getLogWriter() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setLogWriter(PrintWriter out) throws SQLException { // TODO Auto-generated method stub } @Override public void setLoginTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getLoginTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { // TODO Auto-generated method stub return null; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Connection getConnection(String username, String password) throws SQLException { // TODO Auto-generated method stub return null; } }
package com.itheima.uitl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; public class TestPool { @Test public void testPool(){ Connection conn = null; PreparedStatement ps = null; MyDataSource dataSource = new MyDataSource(); try { conn = dataSource.getConnection(); String sql = "insert into account values (null , 'xilali' , 10)"; ps = conn.prepareStatement(sql); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } //歸還鏈接 //conn.close(); //dataSource.addBack(conn); JDBCUtil.release(conn, ps); } } }
package com.itheima.jdbc.util; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一個屬性配置對象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用類加載器,去讀取src底下的資源文件。 後面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //導入輸入流。 properties.load(is); //讀取屬性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取鏈接對象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //靜態代碼塊 ---> 類加載了,就執行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 創建鏈接 參數一: 協議 + 訪問的數據庫 , 參數二: 用戶名 , 參數三: 密碼。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 釋放資源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st ){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.jdbc.test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import com.itheima.jdbc.util.JDBCUtil; public class MainTest { public static void main(String[] args) { //查詢 Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 獲取鏈接對象 conn = JDBCUtil.getConn(); //2. 根據鏈接對象,獲得statement st = conn.createStatement(); //3. 執行sql語句,返回ResultSet String sql = "select * from t_stu"; rs= st.executeQuery(sql); //4. 遍歷結果集 while(rs.next()){ String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(name+" " + age); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } }
package com.itheima.jdbc.test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import com.itheima.jdbc.util.JDBCUtil; /** * 使用junit執行單元測試 */ public class TestDemo { @Test public void testQuery() { // 查詢 Connection conn = null; Statement st = null; ResultSet rs = null; try { // 1. 獲取鏈接對象 conn = JDBCUtil.getConn(); // 2. 根據鏈接對象,獲得statement st = conn.createStatement(); // 3. 執行sql語句,返回ResultSet String sql = "select * from t_stu"; rs = st.executeQuery(sql); // 4. 遍歷結果集 while (rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(name + " " + age); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.release(conn, st, rs); } } @Test public void testInsert(){ // 查詢 Connection conn = null; Statement st = null; try { // 1. 獲取鏈接對象 conn = JDBCUtil.getConn(); // 2. 根據鏈接對象,獲得statement st = conn.createStatement(); //3. 執行添加 String sql = "insert into t_stu values(null , 'aobama' , 59)"; //影響的行數, ,若是大於0 代表操做成功。 不然失敗 int result = st.executeUpdate(sql); if(result >0 ){ System.out.println("添加成功"); }else{ System.out.println("添加失敗"); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, st); } } @Test public void testDelete(){ // 查詢 Connection conn = null; Statement st = null; try { // 1. 獲取鏈接對象 conn = JDBCUtil.getConn(); // 2. 根據鏈接對象,獲得statement st = conn.createStatement(); //3. 執行添加 String sql = "delete from t_stu where name='aobama'"; //影響的行數, ,若是大於0 代表操做成功。 不然失敗 int result = st.executeUpdate(sql); if(result >0 ){ System.out.println("刪除成功"); }else{ System.out.println("刪除失敗"); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, st); } } @Test public void testUpdate(){ // 查詢 Connection conn = null; Statement st = null; try { // 1. 獲取鏈接對象 conn = JDBCUtil.getConn(); // 2. 根據鏈接對象,獲得statement st = conn.createStatement(); //3. 執行添加 String sql = "update t_stu set age = 26 where name ='qyq'"; //影響的行數, ,若是大於0 代表操做成功。 不然失敗 int result = st.executeUpdate(sql); if(result >0 ){ System.out.println("更新成功"); }else{ System.out.println("更新失敗"); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, st); } } }
package com.itheima.dao; /** * 定義操做數據庫的方法 */ public interface UserDao { //update t_user set name=? where id = ? /** * 根據id去更新具體的用戶名 * @param id * @param name */ void update(int id , String name); void delete(int id); /** * 執行添加 * @param userName * @param password */ void insert(String userName , String password); /** * 查詢全部 */ void findAll(); /** * 登陸方法 * @param username * @param password */ void login(String username , String password); }
package com.itheima.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.itheima.dao.UserDao; import com.itheima.uitl.JDBCUtil; public class UserDaoImpl implements UserDao{ @Override public void findAll() { Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 獲取鏈接對象 conn = JDBCUtil.getConn(); //2. 建立statement對象 st = conn.createStatement(); String sql = "select * from t_user"; rs = st.executeQuery(sql); while(rs.next()){ String userName = rs.getString("username"); String password = rs.getString("password"); System.out.println(userName+"="+password); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } /*@Override public void login(String username, String password) { Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 獲取鏈接對象 conn = JDBCUtil.getConn(); //2. 建立statement對象 st = conn.createStatement(); // SELECT * FROM t_user WHERE username='admin' AND PASSWORD='10086' String sql = "select * from t_user where username='"+ username +"' and password='"+ or +"'"; rs = st.executeQuery(sql); if(rs.next()){ System.out.println("登陸成功"); }else{ System.out.println("登陸失敗"); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } }*/ @Override public void login(String username, String password) { Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 獲取鏈接對象 conn = JDBCUtil.getConn(); //2. 建立statement對象 String sql = "select * from t_user where username=? and password=?"; //預先對sql語句執行語法的校驗, ? 對應的內容,後面無論傳遞什麼進來,都把它當作是字符串。 or select PreparedStatement ps = conn.prepareStatement(sql); //? 對應的索引從 1 開始。 ps.setString(1, username); ps.setString(2, password); rs = ps.executeQuery(); if(rs.next()){ System.out.println("登陸成功"); }else{ System.out.println("登陸失敗"); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } @Override public void insert(String userName, String password) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConn(); String sql = "insert into t_user values(null , ? , ?)"; ps = conn.prepareStatement(sql); //給佔位符賦值 從左到右數過來,1 表明第一個問號, 永遠你是1開始。 ps.setString(1, userName); ps.setString(2, password); int result = ps.executeUpdate(); if(result>0){ System.out.println("添加成功"); }else{ System.out.println("添加失敗"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, ps); } } @Override public void delete(int id) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConn(); String sql = "delete from t_user where id = ?"; ps = conn.prepareStatement(sql); //給佔位符賦值 從左到右數過來,1 表明第一個問號, 永遠你是1開始。 ps.setInt(1, id); int result = ps.executeUpdate(); if(result>0){ System.out.println("刪除成功"); }else{ System.out.println("刪除失敗"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, ps); } } @Override public void update(int id, String name) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConn(); String sql = "update t_user set username=? where id =?"; ps = conn.prepareStatement(sql); //給佔位符賦值 從左到右數過來,1 表明第一個問號, 永遠你是1開始。 ps.setString(1, name); ps.setInt(2, id); int result = ps.executeUpdate(); if(result>0){ System.out.println("更新成功"); }else{ System.out.println("更新失敗"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, ps); } } }
package com.itheima.test; import org.junit.Test; import com.itheima.dao.UserDao; import com.itheima.dao.impl.UserDaoImpl; public class TestUserDaoImpl { @Test public void testInsert(){ UserDao dao = new UserDaoImpl(); dao.insert("aobama", "911"); } @Test public void testUpdate(){ UserDao dao = new UserDaoImpl(); dao.update(2, "itheima"); } @Test public void testDelete(){ UserDao dao = new UserDaoImpl(); dao.delete(30); } @Test public void testFindAll(){ //面向父類編程 接口編程 UserDao dao = new UserDaoImpl(); //體現多態的特徵 // UserDaoImpl dao = new UserDaoImpl(); dao.findAll(); } // "10087 "+" or 1=1" === 「10087 or 1=1」 @Test public void testLogin(){ UserDao dao = new UserDaoImpl(); dao.login("admin", "100234khsdf88' or '1=1"); // dao.login("admin", "10087 "+" or 1=1"); // select * from t_user where username='admin' and password='100234khsdf88'or '1=1' // SELECT * FROM t_user WHERE username='admin' AND PASSWORD='10087' or '1=1' } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一個屬性配置對象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用類加載器,去讀取src底下的資源文件。 後面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //導入輸入流。 properties.load(is); //讀取屬性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取鏈接對象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //靜態代碼塊 ---> 類加載了,就執行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 創建鏈接 參數一: 協議 + 訪問的數據庫 , 參數二: 用戶名 , 參數三: 密碼。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 釋放資源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class MyServlet */ @WebServlet("/MyServlet") public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public MyServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 類加載器: classes 目錄 getClass().getClassLoader().getResourceAsStream("aa.txt"); // servletCotnext 取東西 D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test // getServletContext().getResourceAsStream(""); // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\WEB-INF/classes/aa.txt // String path = getServletContext().getRealPath("WEB-INF/classes/aa.txt"); // System.out.println("path="+path); // -------------------------------------------------- // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\ // String path = getServletContext().getRealPath("aa\aa.txt"); // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\WEB-INF/classes // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\aa\aa.txt getClass().getClassLoader().getResourceAsStream(""); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
package com.itheima.jdbc.util; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一個屬性配置對象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用類加載器,去讀取src底下的資源文件。 後面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //導入輸入流。 properties.load(is); //讀取屬性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 獲取鏈接對象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //靜態代碼塊 ---> 類加載了,就執行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 創建鏈接 參數一: 協議 + 訪問的數據庫 , 參數二: 用戶名 , 參數三: 密碼。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 釋放資源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st ){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.test; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.Test; import com.itheima.jdbc.util.JDBCUtil; public class TestDemo implements Serializable{ @Test public void test02(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣錢, 扣ID爲1 的100塊錢 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); //int a = 10 /0 ; String s = null; s.length(); //加錢, 給ID爲2 加100塊錢 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } } @Test public void testTransaction(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); //鏈接,事務默認就是自動提交的。 關閉自動提交。 conn.setAutoCommit(false); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣錢, 扣ID爲1 的100塊錢 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); int a = 10 /0 ; //加錢, 給ID爲2 加100塊錢 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); //成功: 提交事務。 conn.commit(); } catch (SQLException e) { try { //事變: 回滾事務 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } } }
package com.itheima.test; public class MainTest { public static void main(String[] args) { /*Waiter waiter = new Waitress(); waiter.service();*/ WaitressWrap waitressWrap = new WaitressWrap(new Waitress()); waitressWrap.service(); } }
package com.itheima.test; public interface UserDao { void insert(); void login(String username , String password ); // .... }
package com.itheima.test; public interface Waiter { void service(); }
package com.itheima.test; public class Waitress implements Waiter { @Override public void service() { System.out.println("在服務..."); } }
package com.itheima.test; public class WaitressWrap implements Waiter { Waiter watier = null; public WaitressWrap(Waiter watier){ this.watier = watier; } @Override public void service() { System.out.println("微笑:::"); watier.service(); } }