JDBC(二)數據庫連接池和事務

數據庫連接池(數據源)

首先創建一批連接,放在容器中,在需要連接的時候,就從中獲取一個連接,用完之後,再還回池中

數據庫連接池的優點

傳統的數jdbc據庫查詢,創建連接對象,查詢完畢關閉連接對象,會耗時,沒有複用,效率很低

使用連接池,可以實現連接的複用,減少連接創建關閉次數,提高效率

C3P0連接池的三種使用方式

方式1:直接在代碼中使用

	private static void loginPBc3p0() {
		Connection connection=null;
		PreparedStatement preparedStatement=null;
		ResultSet resultSet=null;
		ComboPooledDataSource comboPooledDataSource=new ComboPooledDataSource();
		try {
			comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
			//localhost:3306可以省略
			comboPooledDataSource.setJdbcUrl("jdbc:mysql:///數據庫名?characterEncoding=UTF-8");
			comboPooledDataSource.setUser("數據庫登錄名");
			comboPooledDataSource.setPassword("數據庫登錄密碼");
			
			connection=comboPooledDataSource.getConnection();
			
			String sql="select * from people";
			preparedStatement=connection.prepareStatement(sql);
			
			resultSet=preparedStatement.executeQuery();
			while(resultSet.next()) {
				String name_sql=resultSet.getString("name");
				System.out.println(name_sql);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JdbcUtil.close(resultSet, preparedStatement, connection);
		}
	}

方式2:創建xml文件放在項目根目錄(推薦用xml文件的形式

  • 創建一個c3p0-config.xml文件,這個文件名是固定的,放在src目錄下

點擊菜單欄File,選擇other,創建c3p0-config.xml

文件內容

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///數據庫名?characterEncoding=UTF-8</property>
        <property name="user">數據庫登錄名</property>
        <property name="password">數據庫登錄密碼</property>
        
    </default-config>
</c3p0-config>

java類中的,這幾行註釋就可以了

// comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");

// //localhost:3306可以省略

// comboPooledDataSource.setJdbcUrl("jdbc:mysql:///sujianda?characterEncoding=UTF-8");

// comboPooledDataSource.setUser("root");

// comboPooledDataSource.setPassword("wojiaosujianda99");


方式3:創建properties文件

在src目錄下創建名字爲c3p0.properties的文件

點擊菜單欄File,選擇other,創建c3p0.properties

文件內容

c3p0.driverClass=com.mysql.cj.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///數據庫名?characterEncoding=UTF-8
c3p0.user=數據庫登錄名
c3p0.password=數據庫登錄密碼

同樣的 也要把java文件中的那4行註釋掉

事務

把一堆SQL語句綁定在一起執行,只有兩種情況,要麼全部執行成功,要麼全部執行失敗

它有4個特性

  • 原子性:事務中的所有操作是一個整體,不可以再分割,要麼全部執行成功,要麼全部執行失敗

  • 一致性:事務前後的業務數據保持一致

  • 隔離性:多個事務之間具有隔離性,不會互相訪問,一個事務不能訪問另一個事務正在執行的狀態,只有隔離性等級高可以完全隔離開。

  • 永久性:如果事務中的SQL語句全部執行成功,事務就會提交,此時結果就會保存到數據庫

MySQL事務操作

  • 開啓事務:start transaction;

  • 結束事務:提交(commit;)或回滾(rollback;)


假如有這樣一張表

通過事務,我讓張飛給趙雲轉賬100;

執行SQL語句:

  1. start transaction;

  2. update people set salary=salary-100 where name='張飛';

  3. commit;    //只有commit之後,數據庫裏的數據纔會最終改變

事務對併發讀問題

  • 髒讀:讀到另一個事務的未提交的更新數據;

  • 不可重複讀:一個事務在讀取數據的時候,兩次查詢結果不一致,因爲另一個事務對該記錄做了修改

  • 幻讀或者叫虛讀:對同一張表的兩次查詢不一致,因爲另一個事務插入裏一條記錄,針對插入或刪除操作

MySql默認不允許出現髒讀和不可重複讀

事務的隔離級別

事務隔離級別,就是爲了解決上面幾種問題而誕生的。爲什麼要有事務隔離級別,因爲事務隔離級別越高,在併發下會產生的問題就越少,但同時付出的性能消耗也將越大,因此很多時候必須在併發性和性能之間做一個權衡。所以設立了幾種事務隔離級別,以便讓不同的項目可以根據自己項目的併發情況選擇合適的事務隔離級別,對於在事務隔離級別之外會產生的併發問題,在代碼中做補償。一般不需要手動改

1、READ_UNCOMMITTED

讀未提交,可能出現任何事務併發問題(髒讀,不可重複度,幻讀),性能最好,但是不用;

2、READ_COMMITED(Oracle數據庫默認的)

讀已提交,即能夠讀到那些已經提交的數據,防止髒讀,沒有處理不可重複讀和幻讀;性能次之;

3、REPEATABLE_READ(MySql默認)

可重複讀,防止髒讀和不可重複讀,沒有處理幻讀,性能再次之;

4、SERLALIZABLE

串行化,不會出現任何併發讀問題,性能最差

5、DEFAULT

默認隔離級別,每種數據庫支持的事務隔離級別不一樣,如果Spring配置事務時將isolation設置爲這個值的話,那麼將使用底層數據庫的默認事務隔離級別。順便說一句,如果使用的MySQL,可以使用"select @@tx_isolation"來查看默認的事務隔離級別

網上專門有圖用表格的形式列出了事務隔離級別解決的併發問題:

再必須強調一遍,不是事務隔離級別設置得越高越好,事務隔離級別設置得越高,意味着勢必要花手段去加鎖用以保證事務的正確性,那麼效率就要降低,因此實際開發中往往要在效率和併發正確性之間做一個取捨,一般情況下會設置爲READ_COMMITED,此時避免了髒讀,併發性也還不錯,之後再通過一些別的手段去解決不可重複讀和幻讀的問題就好了。

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章