學習java第44天
努力努力在努力,堅持堅持在堅持!
今天學習了連接池
1.我們可以手動寫連接池需要寫的類實現DataSource,我們創建個靜態集合用來充當池,然後在靜態代碼塊中寫個循環往集合中放入
2.德魯伊,我額們需要導入炸包,然後我們在創建配置文件database.properties裏面的內容,在原先的基礎上加上鍊接池的初始連接數,最大連接,最小連接,以及超時等待時間(毫秒數),連接池就改爲了一個DruidDataSource的對象ds存儲 //使用德魯伊工廠創建連接池 ds = (DruidDataSource) ruidDataSourceFactory.createDataSource(properties);
獲取連接就爲ds.getConnection();
3.事務的處理,需要把線程和連接數據庫對象綁定在一起,確定在調用所有DAO中的方法保持連接的數據庫是一至的這樣才能確定事務的原子性,conn.setAutoCommit(false);//關閉自動提交,事務的開始,conn.commit()執行成功無異常提交,conn.rollback()回滾放在catch中異常就啓動,要在事務都執行完之後,才關閉事務開始之前開啓的connection對象
jdbc配置文件,存儲數據庫的驅動,鏈接地址,用戶名,密碼
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/account?useUnicode=true&characterEncoding=utf8
username=root
password=740056981
數據庫註冊驅動,連接數據庫,釋放資源的工具類
package com.qf.day4.account;
import com.qf.day4.t3.DBUtils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DButil {
private static final Properties properties = new Properties();
//爲當前線程綁定一個Connection連接。從頭到尾
private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<Connection>();
static {
InputStream is = DBUtils.class.getResourceAsStream("/db.properties");
try {
properties.load(is);//將配置文件內的信息通過is輸入流讀到properties集合中
Class.forName(properties.getProperty("driver"));
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
//在ThreadLocal裏取
Connection conn = THREAD_LOCAL.get();//一個事務他只會去一次,第二次再取的話線程裏面就存在了,直接就返回線程裏的連接了
try {
//沒有 ,新建
if(conn == null){
conn = DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username"),properties.getProperty("password"));
THREAD_LOCAL.set(conn);//存到線程中
}
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void closeAll(Connection conn , Statement st, ResultSet re){
try {
if (re != null) {
re.close();
}
if (st != null) {
st.close();
}
if (conn != null) {
conn.close();
THREAD_LOCAL.remove();//關閉連接後,移除線程中綁定的連接對象。在執行下一個操作前解除
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
數據表t_account的實體類
package com.qf.day4.account;
public class t_account {
private String cid;
private String password;
private String username;
private double balance;
private String phone;
@Override
public String toString() {
return "t_account{" +
"cid='" + cid + '\'' +
", password='" + password + '\'' +
", username='" + username + '\'' +
", balance=" + balance +
", phone='" + phone + '\'' +
'}';
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public t_account(String cid, String password, String username, double balance, String phone) {
this.cid = cid;
this.password = password;
this.username = username;
this.balance = balance;
this.phone = phone;
}
public t_account(String cid) {
this.cid = cid;
}
}
t_account的數據對象訪問的工具類(只實現了查單個和修改方法)
package com.qf.day4.account;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class t_accountDaoImpl {
private Connection conn =null;
private PreparedStatement pre = null;
private ResultSet re = null;
//查單個
public t_account select(String cid){
conn = DButil.getConnection();
String sql = "select cardid,password,username,balance,phone from t_account where cardid = ?";
try {
pre = conn.prepareStatement(sql);
pre.setString(1,cid);
re = pre.executeQuery();
if(re.next()){
t_account t1 = new t_account(re.getString(1),re.getString(2),re.getString(3),re.getDouble(4),re.getString(5));
return t1;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DButil.closeAll(null,pre,re);
}
return null;
}
//修改
public int upDate(t_account t){
conn = DButil.getConnection();
String sql = "update t_account set password=?,username=?,balance=?,phone=? where cardid = ? ";
try {
pre = conn.prepareStatement(sql);
pre.setString(1,t.getPassword());
pre.setString(2,t.getUsername());
pre.setDouble(3,t.getBalance());
pre.setString(4,t.getPhone());
pre.setString(5,t.getCid());
return pre.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DButil.closeAll(null,pre,re);
}
return 0;
}
}
t_account業務層(實現了轉賬)業務層的主要作用是在用戶和數據層中間進行接收用戶傳入的數據調用數據層的方法實現用戶想要的功能
package com.qf.day4.account;
import java.sql.Connection;
import java.sql.SQLException;
public class t_accountServiceImpl {
public String tranSfer(String cid,String password,String toid,double money){
//2.組織業務功能
t_accountDaoImpl td = new t_accountDaoImpl();
Connection conn = null;//拿一個連接
try {
//建立了一個數據庫連接
conn = DButil.getConnection();
conn.setAutoCommit(false);//關閉自動提交,事務的開始
//1.驗證自己的賬戶存不存在
t_account t1 = td.select(cid);
if(t1 == null){
return "用戶不存在";
}
//賬戶存在,密碼是否正確
if(!t1.getPassword().equals(password)){
return "密碼錯誤";
}
//賬戶和密碼都對,查看轉賬金額是否大於餘額
if(t1.getBalance()<=money){
return "餘額不足";
}
//查詢轉賬的賬戶是否存在
t_account t2 = td.select(toid);
if(t2 == null){
return "對方賬戶不存在";
}
//自己的餘額進行扣除轉賬金額
t1.setBalance(t1.getBalance()- money);//把自己的對象屬性做了修改
int i = td.upDate(t1);
// int i1 = 1/0;
//對方賬戶加錢
t2.setBalance(t2.getBalance()+money);
int i2 = td.upDate(t2);
conn.commit();//提交
return "轉賬成功";
} catch (Exception e) {
try {
conn.rollback();//回滾
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally {
DButil.closeAll(conn,null,null);
}
return "轉賬失敗";
}
}
測試類
package com.qf.day4.account;
public class Test {
public static void main(String[] args) {
t_accountServiceImpl ts = new t_accountServiceImpl();
String a = ts.tranSfer("b107","123","b104",2000);
System.out.println(a);
}
}