第1 章 : 事務處理
課時1 事務的四大特性(ACID)
原子性
Atomicity 操作不可再分割,要麼成功,要麼失敗
一緻性 Consistency 資料狀态與業務規則保持一緻
隔離性 Isolation 并發事務不會互相幹擾
持久性 Durability 資料操作必須被持久化到資料庫中
課時2:MySQL中開啟和關閉事務
預設情況下,MySQL沒執行一條SQL語句,都是單獨的事務
如果要在一個事務中包含多條SQL語句,那麼需要開啟事務和結束事務
-- 開啟事務
start transaction
-- 結束事務
commit
-- 或者
rollback
課時3 JDBC中完成事務處理
// 開啟事務,設定不自動送出, 預設true
conn.setAutoCommit(false);
// 送出事務
conn.commit()
// 復原事務
conn.rollback()
代碼格式
try{
conn.setAutoCommit(false);
...
conn.commit()
}catch(){
conn.rollback()
}
轉賬示例
import util.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* create table account(
* id int primary key auto_increment,
* username varchar(50),
* balance int
* )
*
* insert into account(username, balance) values ('張三', 1000), ('王五', 1000)
*/
class Demo {
public static void transferMoney(int fromId, int toId, int money) throws SQLException {
Connection conn = JdbcUtils.getConnection();
conn.setAutoCommit(false);
try {
updateBalance(conn, fromId, -money);
if(true){
throw new RuntimeException("斷網了");
}
updateBalance(conn, toId, money);
conn.commit();
} catch (Exception e) {
conn.rollback();
throw new RuntimeException(e);
} finally {
conn.close();
}
}
public static void updateBalance(Connection conn, int id, int money) throws SQLException {
String sql = "update account set balance = balance + ? where id = ?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setInt(1, money);
statement.setInt(2, id);
statement.executeUpdate();
}
public static void main(String[] args) throws SQLException {
transferMoney(1, 2, 100);
}
}
課時4 事務的隔離級别
事務并發問題
髒讀:讀取到另一個事務未送出資料
不可重複讀:兩次讀取不一緻
幻讀:讀到另一個事務已送出資料
四大隔離級别
串行化 不會出現并發,性能最差(堅決不用)
可重複度 防止髒讀和不可重複讀,不能處理幻讀(MySQL預設)
讀已送出 防止髒讀
讀未送出 性能最好
-- 檢視隔離級别
select @@tx_isolation
-- 設定隔離級别
set transaction isolationlevel [1, 2, 3, 4]
第2 章 : 連接配接池
課時5 dbcp連接配接池
1、池參數
初始大小:10個
最小空閑連接配接數:3個
增量:一次建立最小機關5個
最大空閑連接配接數:12個
最大連接配接數:20個
最大等待時間:1000毫秒
2、四大連接配接參數
連接配接池也是使用4個連接配接參數來完成建立連接配接對象
3、連接配接池必須實作接口:
javax.sql.DataSource
連接配接池的close() 方法不是關閉,而是歸還
依賴
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.8.0</version>
</dependency>
]
import org.apache.commons.dbcp2.BasicDataSource;
import java.sql.Connection;
import java.sql.SQLException;
class Demo {
public static void main(String[] args) throws SQLException {
// 配置4個必要參數
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/data");
dataSource.setUsername("root");
dataSource.setPassword("123456");
// 配置連接配接池參數
dataSource.setMaxWaitMillis(1000);
// 擷取連接配接對象
Connection conn = dataSource.getConnection();
System.out.println(conn.getClass().getName());
// 歸還連接配接
conn.close();
}
}
課時6 裝飾者模式
對象增強的手段
(1)繼承
(2)裝飾者模式
(3)動态代理
1、繼承:
會使得類增多
增強的内容是固定的
被增強的對象也是固定的
2、裝飾者模式
增強的對象是不能修改的
被增強的對象可以是任意的
InputStream
FileInputStream 節點流
BufferedInputStream 裝飾流
is a
has a
use a
// MyConnection is Connection
class MyConnection implements Connection{
// MyConnection has Connection
private Connection conn; // 底層對象,被增強的對象
// 通過構造器傳遞底層對象
public MyConnection(Connection conn){
this.conn = conn;
}
public Statement createStatement(){
return this.conn.createStatement();
}
// 增強點
public void close(){
}
}
3、動态代理
被增強的對象可以切換
增強的内容也可以切換
課時7 c3p0連接配接池的基本使用方式
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
class Demo {
public static void main(String[] args) throws PropertyVetoException, SQLException {
// 配置4個必要參數
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/data");
dataSource.setUser("root");
dataSource.setPassword("123456");
// 配置連接配接池參數
dataSource.setAcquireIncrement(5);
dataSource.setInitialPoolSize(3);
dataSource.setMinPoolSize(3);
dataSource.setMaxPoolSize(20);
// 擷取連接配接對象
Connection conn = dataSource.getConnection();
System.out.println(conn.getClass().getName());
// 歸還連接配接
conn.close();
}
}
課時8 c3p0連接配接的配置檔案使用
必須命名為:c3p0-config.xml
必須放在src目錄下
<?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://localhost:3306/data</property>
<property name="user">root</property>
<property name="password">123456</property>
<!-- 池參數配置 -->
<property name="acquireIncrement">3</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">2</property>
<property name="maxPoolSize">10</property>
</default-config>
</c3p0-config>
連接配接會報錯:java.sql.SQLException: No suitable driver
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.SQLException;
class Demo {
public static void main(String[] args) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 擷取連接配接對象
Connection conn = dataSource.getConnection();
System.out.println(conn.getClass().getName());
// 歸還連接配接
conn.close();
}
}
第3 章 : JDBC工具類
課時9-10 JdbcUtils小工具
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class JdbcUtil {
// 需要配置c3p0-config.xml
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 傳回連接配接對象
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 傳回連接配接池對象
public static DataSource getDataSource(){
return dataSource;
}
}
課時11 JNDI配置
JNDI(Java Naming and Directory Interface, Java命名和目錄接口)
課時12 ThreadLocal
解決多線程并發問題的工具類,它為每個線程提供了一個本地的副本變量機制,
實作了和其它線程隔離,并且這種變量隻在本線程的生命周期内起作用,
可以減少同一個線程内多個方法之間的公共變量傳遞的複雜度
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
class Demo {
public static void main(String[] args) throws SQLException {
ThreadLocal<String> tl = new ThreadLocal<String>();
// 添加
tl.set("Tom");
// 擷取
String name = tl.get();
System.out.println(name);
// 移除
tl.remove();
}
}
ThreadLocal的核心代碼
class TL<T>{
private Map<Thread, T> map = new HashMap<Thread, T>();
public void set(T value){
this.map.put(Thread.currentThread(), value);
}
public T get(){
return this.map.get(Thread.currentThread());
}
public void remove(){
this.map.remove(Thread.currentThread());
}
}
課時13 dbutils原理
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
示例
Student.class
public class Student {
private int sid;
private String sname;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
'}';
}
}
Demo.class
1、查詢操作
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
class Demo {
public static void main(String[] args) throws SQLException {
// 提供資料庫連接配接池
QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
// 查詢操作
// sql模闆
String sql = "select * from student where sid = ?";
// 參數
Object[] params = {3};
// 提供結果集處理器
Student student = qr.query(sql, new BeanHandler<Student>(Student.class), params);
System.out.println(student);
// Student{sid=3, sname='楊不悔'}
}
}
2、更新操作
String sql = "update student set sname=? where sid = ?";
Object[] params = {"楊不悔", 3};
qr.update(sql, params);
課時14 dbUtils結果集處理器介紹
common-dbutils.jar
QueryRunner
// update執行增,删,改
int update(String sql, Object... params)
int update(Connection conn, String sql, Object... params)
// query執行查詢
T query(String sql, ResultSetHandler rsh, Object... params)
T query(Connection conn, String sql, ResultSetHandler rsh, Object... params)
ResultSetHandler接口
BeanHandler(單行) 一行轉換成指定類型的javaBean對象
BeanListHandler(多行) 多行轉為list對象
MapHandler(單行) 一行結果轉為Map對象
MapListHandler(多行) 多行結果轉為Map對象清單
ScalarHandler 單行單列 通常用于select count(*) from table
1、BeanListHandler
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
class Demo {
public static void main(String[] args) throws SQLException {
// 提供資料庫連接配接池
QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select * from student";
List<Student> students = qr.query(sql, new BeanListHandler<Student>(Student.class));
System.out.println(students);
}
}
2、MapListHandler
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
class Demo {
public static void main(String[] args) throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select * from student";
List<Map<String, Object>> students = qr.query(sql, new MapListHandler());
System.out.println(students);
}
}
3、ScalarHandler
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
class Demo {
public static void main(String[] args) throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
String sql = "select count(*) from student";
Number cnt = (Number)qr.query(sql, new ScalarHandler());
long count = cnt.longValue();
System.out.println(count);
}
}
課時15 編寫TxQueryRunner配合JdbcUtils來處理事務
class TxQueryRunner extends QueryRunner{
// 重寫部分方法
}
課時16 JdbcUtils處理多線程并發通路問題
使用 ThreadLocal
第4 章 : 分頁
課時17 分頁準備工作
分頁優點:隻查詢一頁,不用查詢所有頁
class pageBean<T>{
// 目前頁碼
private int currentPage;
// 總頁數
private int totalPage;
// 總記錄數
private int totalRecord;
// 頁面大小
private int pageSize;
// 頁面資料
private List<T> beanList;
}
課時18:處理分頁各層分工
第n頁/共N頁 首頁 上一頁 1 2 3 4 5 6 下一頁 尾頁
課時19 分頁處理第一階段完成
課時20 分頁之頁面頁碼清單計算
計算公式
pageSize = 10
begin = currentPage - 5
end = currentPage + 4
如果總頁數<=10, 那麼bedin=1, end=總頁數
頭溢出:當begin<1, 那麼begin=1
尾溢出:當end>總頁數, 那麼end>總頁數
課時21 分頁之查詢條件丢失問題
超連結中要保留參數