1. 程式人生 > 實用技巧 >2020.1.7-jdbc事務 - ### 連線池概念 - **c3p0** - **Driud** - **JDBC Template** - **DBUtils**

2020.1.7-jdbc事務 - ### 連線池概念 - **c3p0** - **Driud** - **JDBC Template** - **DBUtils**

JDBC事務控制
1.什麼是事務:一個包含多個步驟或者業務操作,如果業務或者多個業務被事務管理,則這麼多個步驟要麼同時成功,要麼同時失敗,這些步驟是一個整體不可分割.
2.操作:
開啟事務:mysql----->start transaction
提交事務:commit
回滾事務:rollback
3.使用Connection物件來管理事物
開啟事物:setAutoCommit(boolean autoCommit):-->指定該方法裡面傳入false值,表示開啟事務,開啟事務是 在所有sql語句執行之前
提交事務:commit():--->當前面所有的sql語句執行完畢(不出錯)的時候才能提交事務
回滾事務:rollback():--->當執行事務中sql語句時候,如果失去了語句發生異常那麼就會回滾事務,所以回滾事務的程式碼一般都是放在catch語句塊中
4.示例程式碼:
// 含有事務的轉賬
public static void transform02() {
// 讓張三給李四轉賬10000錢
/*
* 首先讓張三的錢減少10000
* 然後讓李四的錢增加10000
*/
//定義實現轉賬的兩條sql語句
double money = 10000;
String username01 = "張三";
String username02= "李四";

	String sql01 = "update account set balance = balance-? where username = ?";
	String sql02 = "update account set balance = balance+? where username = ?";
	// 使用Connection物件手動開啟事務 setAutoCommit(boolean autoCommit):
	Connection con = DBUtil.getConnection();
	try {
		con.setAutoCommit(false);
		// 通過con獲取預處理物件 先讓張三的錢減少10000
		ps01 = con.prepareStatement(sql01);
		ps01.setDouble(1, money);
		ps01.setString(2, username01);
		// 執行sql語句
		int count = ps01.executeUpdate();
		// 手動製造一個異常
		int i = 1 / 0;
		// 再讓李四的錢增加10000
		// 通過con獲取預處理物件
		ps02 = con.prepareStatement(sql02);
		ps02.setDouble(1, money);
		ps02.setString(2, username02);
		// 執行sql語句
		int coun02 = ps02.executeUpdate();
		// 提交事務
		con.commit();
		System.out.println("轉賬成功!");
	} catch (Exception e) {
		// 事務回滾
		try {
			con.rollback();
			System.out.println("轉賬失敗!");
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		e.printStackTrace();
	}finally {
		// 把開啟的各種連線物件釋放掉
		try {
			ps02.close();
			ps01.close();
			con.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

連線池
1.什麼是連線池
其實就是一個容器,在這個容器當中存放著多個連線物件
當系統開始執行的時候,可以讓系統提前建立多個連線物件,放到容器裡面(連線池),當客戶端需要連線物件時,看洋蔥常量池裡面申請一個連線,去訪問資料庫的時候,當該連線使用完畢的時候,不再釋放歸還給系統,而是把這個連線物件還給連線池.
2.好處:
可以大大節省系統的開銷
可以提高訪問速度

3.實現操作
javax.sql
JNDI--->java命名和目錄介面
使用JNDI降低程式和資料庫耦合度,是你的程式更加方便配置和維護以及部署.
是javaEE中規範中的重要規範之一.是EJB的相關知識.
DateSource介面 他裡面並不提供具體的實現麼事由驅動程式供應商(資料庫廠商提供)

1.c3p0---->一套資料庫連線池的技術
2.druid--->也是一套資料庫連線池技術,由阿里巴巴提供
3.c3p0資料庫連線池技術

步驟:
1.找到 c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar
2.把兩個jar包植入到工程的classpath類路徑下(lib包下),不要忘記匯入mysql驅動jar包,mysql-connector-java.jar
3.在src下面,定義配置檔案;c3p0.properties或者c3p0-config.xml
4.獲取DateSource物件:通過工廠方式來實現,DruidDateSourceFactory
5.從連線池中獲取連線物件,:getConnection()
JDBCTemplate
1.Spring框架挺可憐對JDBC操作的簡單封裝,使用JDBCTemplate物件來簡化JDBC開發流程
2.步驟
1.從官網找到spring-jdbc相關的jar包匯入工程路徑下(lib資料夾)
2.建立JDBCtemplate物件,依賴於DateSource連線池(資料來源)
3.使用HDBCTemplate物件中的api方法實現crud操作
DML操作:update();
DQL操作:查詢不用select用query
query();將查詢的結果集服裝為javaBean物件
query()方法的引數:RowMapper
手動裝配:使用匿名內部類,自定義裝配查詢的每條記錄
自動裝配:使用Spring提供的BeanPropertyRowMapper實現類,完成對資料的自動裝配
具體操作如下:new BeanPropertyRowMapper<型別>(型別.class)
queryForMap():將查詢結果封裝成map集合,只能封裝一條記錄:鍵key是欄位名,值value是欄位 值,結果集記錄數只能是1
queryForList():將結果集服裝為List集合,在list集合中含有多條記錄,每天一條記錄都是一個map集合,List<Map<Object,Object>> list:
queryForObject();將結果封裝成為一個物件,一般用於聚合函式,查詢總記錄數 int count()
具體操作:
// 增刪改動作
// 修改資料
public static void modifyData() {

	int count = jdbcTemplate.update("update account set username = ? where username = ?", "小五","王五");
	System.out.println(count);
}
// 刪除資料
public static void deleteData() {
	int count = jdbcTemplate.update("delete from account where username = ?", "小五");
	System.out.println(count);
}
// 插入一條資料
public static void insertDate() {
	int count = jdbcTemplate.update("insert into account values(null,?,?)", "王五",5000);
	System.out.println(count);
}
public static void test() {
	// 查詢張三的這條資訊 封裝到賬戶物件中
	String username = "張三";
	String sql = "select * from account where username = ?";	
	Map<String, Object> map = jdbcTemplate.queryForMap(sql,username);
	System.out.println(map);// {id=1, username=張三, balance=20000.0}
}

// 簡化手動封裝的方法
public static void queryAll() {
	String sql = "select * from account";
	// Incorrect column count: expected 1, actual 3
	List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
	System.out.println(list);
	
}

// 使用query方法優化queryBean方法
public static void queryBean2() {
	List<Account> list = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
	System.out.println(list);
	
}

// 將查詢到結果集封裝成JavaBean物件
public static void queryBean() {
	String sql = "select * from account where username = '張三'";
	// RowMapper<T>
	List<Account> list = jdbcTemplate.query(sql, new RowMapper<Account>() {
		@Override
		public Account mapRow(ResultSet set, int arg1) throws SQLException {
			// 封裝查詢到每一條記錄值
			Account account = new Account();
			int id = set.getInt(1);
			String username = set.getString(2);
			double balance = set.getDouble(3);
			account.setId(id);
			account.setUsername(username);
			account.setBalance(balance);
			return account;
		}
	});
	
	System.out.println(list);// [Account [id=1, username=張三, balance=20000.0]]
}

// 查詢總記錄   查詢account表中的所有記錄數
public static void queryTotalNum() {
	// queryFoObject()
	Integer count = jdbcTemplate.queryForObject("select count(*) from account", Integer.class);
	System.out.println(count);// 4
}