1. 程式人生 > >事務 與 資料庫連線池【c3p0】 與 DBUtiles學習筆記

事務 與 資料庫連線池【c3p0】 與 DBUtiles學習筆記

1.事務

開啟事務:start transaction;
回滾事務:rollback;
提交事務: commit;
關閉自動提交事務:setAutoCommit(false);
1.1事務的特性ACID【面試】
1.原子性【A】:事務包含的邏輯不可分割
一致性【C】:事務執行前後,資料完整性
隔離性【I】 :事務執行期間不受其他事務影響
永續性【D】:事務執行成功,則資料永久儲存到磁碟上;
1.1.2.事務的安全隱患:
不考慮隔離級別設定:
【讀】:
1.髒讀:>>>一個事務讀到另外一個事務還未提交的資料;
2.不可重複讀:>>>一個事務讀到了另外一個事務提交的資料,造成兩次查詢結果不一致;>>>解決:重複讀:repeatable read

;【預設】
3.幻讀:一個事務讀到另外一個事務已提交插入的資料,導致多次查詢結果不一致。>>>>解決:Serializable【可序列化】最高級別
四個隔離級別的效率從高到低排列:
讀未提交>讀已提交>可重複讀>可序列化
攔截程度相反

【寫】:丟失更新
>>>解決:1.悲觀鎖;
======== 2.樂觀鎖

【mysql預設隔離級別:可重複讀】
【oracle預設隔離級別:讀已提交】
1.1.3在程式碼中使用事務的步驟

Connection conn = JDBCUtil.getConn();
conn.setAutoCommit(false);//關閉事務的自動提交
.....
conn.commit();//提交
conn.roolback();//回滾

2.資料庫連線池

2.1DBCP連線池【瞭解】
dbcp建立dataSource方式:

BasicDataSource dataSource = new BasicDataSource();

2.1.1使用程式碼方式連線【瞭解】
將資料插入到bank下的account表中

public class demo1 {
	@Test
	public void dbcp(){
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//1.構建資料來源物件
			BasicDataSource dataSource = new BasicDataSource();
			dataSource.setDriverClassName("com.mysql.jdbc.Driver");
			dataSource.setUrl("jdbc:mysql://localhost/bank");
			dataSource.setUsername("root");
			dataSource.setPassword("123456");
			//2.獲得連線物件
			conn = dataSource.getConnection();
			String sql = "insert into account values(null,?,?)";
			ps = conn.prepareStatement(sql);
			ps.setString(1, "admin");
			ps.setInt(2, 20000);
			ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			JDBCUtil.release(conn, ps);
		}
	}
}

2.1.2使用配置檔案方式

2.2 c3p0連線池【掌握】
c3p0建立dataSource連線方式:

ComboPooledDataSource dataSource = new ComboPooledDataSource();

2.2.1程式碼連線【瞭解】

public class demo1 {
	@Test
	public void c3p0() throws PropertyVetoException{
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//1.建立dataSource
			ComboPooledDataSource dataSource = new ComboPooledDataSource();
			//2.設定連線資料資訊
			dataSource.setDriverClass("com.mysql.jdbc.Driver");
			dataSource.setJdbcUrl("jdbc:mysql://localhost/bank");
			dataSource.setUser("root");
			dataSource.setPassword("123456");
			
			
			conn = dataSource.getConnection();
			String sql = "insert into account values(null,?,?)";
			ps = conn.prepareStatement(sql);
			ps.setString(1, "aaa");
			ps.setInt(2, 12000);
			ps.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			JDBCUtil.release(conn, ps);
		}
	}
}

2.2.2c3p0配置檔案連線方式【★掌握】
c3p0-config.xml的原始檔

<c3p0-config>
  <default-config>
    <property name="automaticTestTable">con_test</property>
    <property name="checkoutTimeout">30000</property>
    <property name="idleConnectionTestPeriod">30</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>

    <user-overrides user="test-user">
      <property name="maxPoolSize">10</property>
      <property name="minPoolSize">1</property>
      <property name="maxStatements">0</property>
    </user-overrides>

  </default-config>

  <!-- This app is massive! -->
  <named-config name="intergalactoApp"> 
    <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>

所以我們在定義c3p0配置檔案時必須也使用c3p0-config.xml這個名字
在這裡插入圖片描述
c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-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">123456</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>
</c3p0-config>

c3p0_demo2.java

public class c3p0_demo2 {
	@Test
	public void test(){
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			ComboPooledDataSource dataSource = new ComboPooledDataSource();
			//獲得連線物件
			conn = dataSource.getConnection();
			String sql = "insert into account values(null,?,?)";
			ps = conn.prepareStatement(sql);
			ps.setString(1, "c3p0");
			ps.setInt(2, 18000);
			ps.executeUpdate();//執行
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			JDBCUtil.release(conn, ps);//釋放
		}
	}
}

執行後資料庫情況
在這裡插入圖片描述
這裡就把資料插進來了。
【特別注意】xml檔案的命名一定是:c3p0-config.xml,否則就會執行失敗

3.DBUtiles

QueryRunner

//1.c3p0建立連線
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//2.dbUtil只是簡化CRUD的程式碼,但是不可以建立連線
QueryRunner run = new QueryRunner(dataSource);

兩個常用的方法:
1.queryRunner.update();//增刪改
2.queryRunner.query();//查詢
3.1DBUtiles裡的增刪改
dbUtil只是簡化CRUD的程式碼,但是不可以建立連線

public class Tset {
	@Test
	public void testInsert() throws SQLException{
		//1.c3p0建立連線
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		//2.dbUtil只是簡化CRUD的程式碼,但是不可以建立連線
		QueryRunner run = new QueryRunner(dataSource);
		String sql = "insert into account values(null,?,?)";
		//3.增加
		run.update(sql, "dbutil",230000);
		//4.刪除
		run.update("delete from account where id = ?", 8);
		//5.更新
		run.update("update account set money=? where id=?", 20000,4);
	}
}

3.2DBUtiles通用的增刪改方法
通過元資料獲取有幾個?(即佔位符)

	ParameterMetaData metaData = ps.getParameterMetaData();
	int count = metaData.getParameterCount();
public void test(){
		update("insert into account values(null,?,?)", "common",100000);
	}
	
public class CommonUtil {
	public void update(String sql,Object...args){
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = JDBCUtil.getConn();
			ps = conn.prepareStatement(sql);
			ParameterMetaData metaData = ps.getParameterMetaData();//獲取元資料
			int count = metaData.getParameterCount();//獲取個數,這裡獲取?的個數
			
			for (int i = 0; i < count; i++) {
				ps.setObject(i+1, args[i]);
			}
			ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			JDBCUtil.release(conn, ps);
		}
	}
}

3.3DBUtiles裡的查詢
這裡用到泛型,現在Domain層建立一個Account類:
生成set,get方法,重寫String

private String name;
private int money;

(一)程式碼實現
在這裡插入圖片描述
1.查詢單條資料
new BeanHandler<‘T’>(class檔案);

public class Select {
	@Test
	public void selectDemo() throws SQLException{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		QueryRunner runner = new QueryRunner(dataSource);
		//查詢單條資料
		Account account = runner.query("select * from account where id=?",
					new BeanHandler<Account>(Account.class), 9);
		System.out.println(account);
	}
}
Account [name=dbutil, money=230000]

2.查詢多條資料
new BeanListHandler<‘T’>(class);

public class Select {
	@Test
	public void selectDemo() throws SQLException{
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		QueryRunner runner = new QueryRunner(dataSource);
		//查詢單條資料
	List<Account> list= runner.query("select * from account",
					new BeanListHandler<Account>(Account.class));
		System.out.println(list);
	}
}
[Account [name=張三, money=23000], Account [name=李四, money=25000], Account [name=admin, money=20000], Account [name=aaa, money=20000], Account [name=c3p0, money=18000], Account [name=dbutil, money=230000], Account [name=dbutil, money=230000], Account [name=dbutil, money=230000], Account [name=dbutil, money=230000]]