一、JDBC驅(qū)動(dòng)
吉安網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站設(shè)計(jì)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)公司公司2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。
JDBC驅(qū)動(dòng)的加載:
1、通過(guò)容器加載:
對(duì)于有容器的Java應(yīng)用,可以直接將相應(yīng)的驅(qū)動(dòng)jar包放在容器的lib目錄下,例如在Tomcat做容器的web應(yīng)用,將驅(qū)動(dòng)復(fù)制到tomcat的lib子目錄下;
2、應(yīng)用運(yùn)行時(shí)加載:
如果希望應(yīng)用自行加載相應(yīng)的驅(qū)動(dòng),需要maven為應(yīng)用打jar/war包時(shí)指定好搜尋驅(qū)動(dòng)jar時(shí)的classpath,請(qǐng)參考:
https://maven.apache.org/shared/maven-archiver/examples/classpath.html
https://www.cnblogs.com/snaildev/p/8341610.html
示例一(可執(zhí)行jar包下有l(wèi)ib目錄存放依賴jar包):
???????? image ???????????????????? ???????????????????? ????????org.apache.maven.plugins ????????????????maven-jar-plugin ????????????????2.4 ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????????????? ????????????????????true ????????????????????????????lib/ ????????????????????????????some.package.MainClass ????????????????????????
業(yè)務(wù)自行加載JDBC驅(qū)動(dòng)時(shí),需要在應(yīng)用用JDBC之前執(zhí)行如下操作加載驅(qū)動(dòng):
Class.forName("com.MySQL.jdbc.Driver"); //?Then?the?following?begin?to?use?jdbc
二、通過(guò)連接池(DataSource的一種)管理與數(shù)據(jù)庫(kù)的連接
目前常用的連接池為Druid或Hikari,分別說(shuō)明如下:
1、Druid連接池:
maven依賴:
???? com.alibaba ????druid ????1.1.11
示例代碼:
DruidDataSource?createSource(String?name,?String?jdbcUrl,?String?userName,?String?password, ????????maxActive,?minIdle,?maxWait,?scanInterval,?minActiveTime)?{ ????DruidDataSource?src?=?DruidDataSource(); ????src.setName(name); ????src.setUrl(jdbcUrl); ????src.setUsername(userName); ????src.setPassword(password); ????src.setDriverClassName();? ????src.setInitialSize(minIdle); ????src.setMaxActive(maxActive); ????src.setMinIdle(minIdle); ????src.setMaxWait(maxWait);? ????src.setTimeBetweenEvictionRunsMillis(scanInterval);? ????src.setMinEvictableIdleTimeMillis(minActiveTime);??? ????src.setTestWhileIdle();? ????src.setTestOnBorrow();?? ????src.setTestOnReturn(); ????src.setPoolPreparedStatements();? ????src.setMaxPoolPreparedStatementPerConnectionSize();? ????src.setValidationQuery();? ????src.setRemoveAbandoned();? ????src.setRemoveAbandonedTimeout();? ????src.setKeepAlive();? ????if(!isDataSourceOk(src)){ ????????LOGGER.error("Data?source?"+?name?+?"test?failed"); ????} ????return?src; } private?static?boolean?isDataSourceOk(DataSource?source){ ????try?(Connection?connection?=?source.getConnection(); ?????????PreparedStatement?stmt?=?connection.prepareStatement("select?1"); ?????????ResultSet?resultSet?=?stmt.executeQuery()){ ????????resultSet.next(); ????????return?true; ????}catch?(Throwable?e){ ????????return?false; ????} }
2、Hikari連接池
maven依賴:
???? com.zaxxer ????HikariCP ????3.2.0
示例代碼:
HikariDataSource?createSource(String?name,?String?jdbcUrl,?String?userName,?String?password, ????????connectionTimeout,?idleTimeout,?maxLifeTime,?poolSize)?{ ????HikariDataSource?src?=?HikariDataSource(); ????src.setPoolName(name); ????src.setJdbcUrl(jdbcUrl); ????src.setUsername(userName); ????src.setPassword(password); ????src.setDriverClassName();? ????src.setConnectionTimeout(connectionTimeout); ????src.setIdleTimeout(idleTimeout);? ????src.setMaxLifetime(maxLifeTime);? ????src.setMaximumPoolSize(poolSize); ????if(!isDataSourceOk(src)){ ????????LOGGER.error("Data?source?"+?name?+?"test?failed"); ????} ????return?src; }
三、處理連接
1、首先通過(guò)連接池獲取連接,例如:
try(Connection?getConnection()?SQLException?{ ????assert?DataSourceManager.getDataSource()?!=?null; ????return?DataSourceManager.getDataSource().getConnection(); }
2、連接的SQL請(qǐng)求提交方式
從連接池(無(wú)輪DruidDataSource還是HirakiDataSource)申請(qǐng)到Connection對(duì)象拿到后,默認(rèn)的提交方式為自動(dòng)提交,即此時(shí)調(diào)用connection.getAutoCommit()返回的一定是true;
Connection對(duì)象歸還連接池后,下次再?gòu)倪B接池申請(qǐng)一個(gè)Connection,默認(rèn)的提交方式還是自動(dòng)提交。需要清楚什時(shí)候用自動(dòng)提交、什么時(shí)候適合手工提交。
概況起來(lái)就是,看申請(qǐng)到Connection對(duì)象到歸還Connection對(duì)象這期間使用同一個(gè)Connection對(duì)象做了什么操作:
(1)只有讀操作,沒有任何寫操作:用自動(dòng)提交;
(2)只有一次對(duì)單個(gè)表的單條記錄有進(jìn)行寫操作:用自動(dòng)提交;
自動(dòng)提交的代碼示例如下
try(Connection?connection?=?())?{ ????block.apply(connection);?//?Do?all?query?or?only?one?update?for?only?one?record }
(3)對(duì)同一張表的多條記錄進(jìn)行了寫操作,或者對(duì)不同表的記錄分別進(jìn)行了寫操作:根據(jù)是否需要回滾、性能要求,確定是否需要支持事務(wù)性;如果要支持事物性,必須采用手動(dòng)提交;
手動(dòng)提交的操作示例:
try(Connection?connection?=?())?{ ????boolean?success?=?false; ????try{ ????????T?t?=?block.apply(connection);?//?Use?this?connection?process?one?transaction ????????doCommit(connection); ????????success?=?true; ????????return?t; ????}finally{ ????????if(!success)?{ ????????????doRollback(connection);?//?If?possible,?support?rollback?when?failed ????????} ????} } 上述復(fù)雜過(guò)程的block中可能對(duì)connection的提交模式進(jìn)行了修改,為了保持代碼的兼容性,上述doCommit()及doRollback()的設(shè)計(jì)如下: public?static?void?doCommit(Connection?connection)?throws?SQLException?{ ????if?(!connection.getAutoCommit())?{ ????????connection.commit(); ????} } private?static?void?doRollback(Connection?connection)?throws?SQLException?{ ????if?(SUPPORT_ROLLBACK?&&?!connection.getAutoCommit())?{ ????????connection.rollback(); ????} }
(4)耗時(shí)的操作,數(shù)據(jù)量比較大,這時(shí)依賴數(shù)據(jù)庫(kù)的事物性及回滾已經(jīng)沒法達(dá)到;這種情況下應(yīng)該分多次提交,并有應(yīng)用層提供回滾;
示例如下:
try(Connection?connection?=?())?{ ????boolean?success?=?false; ????try{ ????????block1.accept(connection); ????????doCommit(connection); ????????block2.accept(connection); ????????doCommit(connection); ????????success?=?true; ????}finally{ ????????if(!success)?{ ????????????block2.clear(connection); ????????????block1.clear(connection); ????????} ????} }