開篇
?Druid號稱是Java語言中最好的數(shù)據(jù)庫連接池赶盔,并且能夠提供強(qiáng)大的監(jiān)控和擴(kuò)展功能于未。作為日常使用較多的數(shù)據(jù)庫連接組件烘浦,純粹個人興趣研究下理解下的實現(xiàn)原理萍鲸。
?理解一個工具組件最好的方式就是進(jìn)行 debug,這里建議大家下載下參考連接中的 druid demo握侧,修改下具體的數(shù)據(jù)庫連接參數(shù)就可以直接進(jìn)行調(diào)試跟蹤藕咏。
?之所以強(qiáng)調(diào) Demo 的重要性秽五,在于通過 demo 能夠跟蹤所有的執(zhí)行流程饥悴,有了 Demo 剩下的事情只要花時間都能很好的梳理。
Druid的調(diào)試
url=jdbc:mysql://localhost:3306/github_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true
username=root
password=123456
name=zzs001
driverClassName=com.mysql.cj.jdbc.Driver
initialSize=4
maxActive=8
minIdle=0
maxWait=-1
poolPreparedStatements=false
maxOpenPreparedStatements=10
validationQuery=select 1 from dual
validationQueryTimeout=-1
testOnBorrow=false
testOnReturn=false
testWhileIdle=true
timeBetweenEvictionRunsMillis=-1
minEvictableIdleTimeMillis=1800000
defaultAutoCommit=true
defaultReadOnly=false
defaultTransactionIsolation=REPEATABLE_READ
defaultCatalog=github_demo
removeAbandoned=false
removeAbandonedTimeoutMillis=300*1000
logAbandoned=true
filters=log4j,wall,mergeStat
connectionProperties=druid.useGlobalDataSourceStat=true;druid.stat.logSlowSql=true;druid.stat.slowSqlMillis=5000
accessToUnderlyingConnectionAllowed=false
init=true
- 基礎(chǔ)的配置信息如上,核心在于 JDBC 的連接地址信息贷揽。
public class DruidDataSourceTest {
@Test
public void save() throws SQLException {
// 創(chuàng)建sql
String sql = "insert into demo_user values(null,?,?,?,?,?)";
Connection connection = null;
PreparedStatement statement = null;
try {
// 獲得連接
connection = JDBCUtils.getConnection();
// 開啟事務(wù)設(shè)置非自動提交
connection.setAutoCommit(false);
// 獲得Statement對象
statement = connection.prepareStatement(sql);
// 設(shè)置參數(shù)
statement.setString(1, "zzf003");
statement.setInt(2, 18);
statement.setDate(3, new Date(System.currentTimeMillis()));
statement.setDate(4, new Date(System.currentTimeMillis()));
statement.setBoolean(5, false);
// 執(zhí)行
statement.executeUpdate();
// 提交事務(wù)
connection.commit();
} finally {
// 釋放資源
JDBCUtils.release(connection, statement, null);
}
}
}
- 核心步驟獲獲取 Connection 并設(shè)置并通過 Connection 設(shè)置statement蓖救,最后通過statement進(jìn)行 SQL 的執(zhí)行印屁。
public class JDBCUtils {
private static DataSource dataSource;
private static ThreadLocal<Connection> tl = new ThreadLocal<>();
private static final Log log = LogFactory.getLog(JDBCUtils.class);
static {
init();
}
private static void init() {
Properties properties = new Properties();
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
try {
properties.load(in);
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch(Exception e) {
throw new RuntimeException("創(chuàng)建數(shù)據(jù)源失敗", e);
}
}
/**
* <p>獲取數(shù)據(jù)庫連接對象的方法雄人,線程安全</p>
* @return: Connection
*/
public static Connection getConnection() throws SQLException {
// 從當(dāng)前線程中獲取連接對象
Connection connection = tl.get();
// 判斷為空的話,創(chuàng)建連接并綁定到當(dāng)前線程
if(connection == null) {
connection = createConnection();
tl.set(connection);
}
return connection;
}
/**
* <p>創(chuàng)建數(shù)據(jù)庫連接</p>
* @return: Connection
* @throws SQLException
*/
private static Connection createConnection() throws SQLException {
Connection conn = null;
// 獲得連接
conn = dataSource.getConnection();
return conn;
}
}
- 通過DruidDataSourceFactory創(chuàng)建 DataSource叉谜。
- 通過DataSource獲取 Connection正罢。