spring jdbcTemplate結合資料庫連線池
阿新 • • 發佈:2019-01-06
上一篇, 我們使用了spring一個自帶的 org.springframework.jdbc.datasource.DriverManagerDataSource管理類操作jdbcTemplate,這是一個不帶連線池的資料來源管理驅動類。在這個驅動類的管理下,程式中jdbcTemplate的每次獲取連線都會直接向資料庫申請建立連線,比較耗費資源。這一篇中,我們嘗試將第三方資料連線池框架(阿里巴巴druid)整合到spring的JdbcTemplate中 。
示例程式碼:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!-- 防止記憶體洩漏spring監聽器 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!-- spring web容器監聽器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tingcream</groupId> <artifactId>spring-jdbc</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>spring-jdbc</name> <url>http://maven.apache.org</url> <dependencies> <!-- junit 測試框架 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- servlet api 包,引入後無需再引入tomcat lib目錄下面的包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp api 包,引入後無需再引入tomcat lib目錄下面的包 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <!-- jstl 標籤庫依賴jar包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- 阿里巴巴 fastJson 解析器 jar包 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.31</version> </dependency> <!-- spring 核心jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring beans jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring 事務管理jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring 容器上下文 jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring 容器 上下文支援jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring web相關元件jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring mvc 支援jar包 --> <!-- <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.2.RELEASE</version> </dependency> --> <!-- spring aop 切面jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring 切面 織入jar包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring-jdbc 事務支援jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- spring 測試支援jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.2.RELEASE</version> </dependency> <!-- mysql jdbc 驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <!-- druid 阿里巴巴資料庫連線池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> <exclusions> <exclusion> <artifactId>jconsole</artifactId> <groupId>com.alibaba</groupId> </exclusion> <exclusion> <artifactId>tools</artifactId> <groupId>com.alibaba</groupId> </exclusion> </exclusions> </dependency> </dependencies> <build> <finalName>spring-jdbc</finalName> </build> </project>
spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd"> <!-- spring 元件包掃描 --> <context:component-scan base-package="com.tingcream.springJdbc"> </context:component-scan> <!-- <bean id="jdbcTemplateFactory" class="com.tingcream.springJdbc.jdbcTemplate.JdbcTemplateFactory"> </bean> <bean id="jdbcTemplate" factory-bean="jdbcTemplateFactory" factory-method="getJdbcTemplate"> </bean> --> <!-- 引入外部配置檔案 (可含多個) --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> </list> </property> </bean> <!--阿里巴巴資料庫連線池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}" /> <!-- 初始化連線數量 --> <property name="initialSize" value="${druid.initialSize}"/> <!--最大併發連線數 --> <property name="maxActive" value="${druid.maxActive}" /> <!-- 最小空閒連線數 --> <property name="minIdle" value="${druid.minIdle}"/> <!-- 配置獲取連線等待超時的時間 --> <property name="maxWait" value="${druid.maxWait}"/> <!-- 超過時間限制是否回收 --> <property name="removeAbandoned" value="${druid.removeAbandoned}"/> <!-- 超過時間限制多長; --> <property name="removeAbandonedTimeout" value="${druid.removeAbandonedTimeout}"/> <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}"/> <!-- 配置一個連線在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}"/> <!-- 用來檢測連線是否有效的sql,要求是一個查詢語句 --> <property name="validationQuery" value="${druid.validationQuery}"/> <!-- 申請連線的時候檢測 --> <property name="testWhileIdle" value="${druid.testWhileIdle}" /> <!-- 申請連線時執行validationQuery檢測連線是否有效,配置為true會降低效能 --> <property name="testOnBorrow" value="${druid.testOnBorrow}"/> <!-- 歸還連線時執行validationQuery檢測連線是否有效,配置為true會降低效能 --> <property name="testOnReturn" value="${druid.testOnReturn}"/> <!-- 開啟PSCache,並且指定每個連線上PSCache的大小 --> <property name="poolPreparedStatements" value="${druid.poolPreparedStatements}"/> <property name="maxPoolPreparedStatementPerConnectionSize" value="${druid.maxPoolPreparedStatementPerConnectionSize}"/> <!-- 屬性型別是字串,通過別名的方式配置擴充套件外掛, 常用的外掛有: 監控統計用的filter:stat 日誌用的filter:log4j 防禦SQL注入的filter:wall --> <property name="filters" value="${druid.filters}"/> </bean> <!-- jdbcTemplate bean配置 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
jdbc.properties
#驅動全類名
jdbc.driverClassName = com.mysql.jdbc.Driver
#本機環境
jdbc.url =jdbc:mysql://localhost:3306/myDB?useUnicode=true&characterEncoding=UTF8&useSSL=false
jdbc.username = root
jdbc.password = 123456
#初始化連線數
druid.initialSize = 3
#最大活躍連線數
druid.maxActive = 10
#最小空閒連線數
druid.minIdle = 2
#最大連線等待時間 毫秒
druid.maxWait = 60000
#超過時間限制是否回收
druid.removeAbandoned = true
#超時丟棄連線 1800秒 即30分鐘
druid.removeAbandonedTimeout = 1800
#配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
druid.timeBetweenEvictionRunsMillis = 60000
#配置一個連線在池中最小生存的時間,單位是毫秒
druid.minEvictableIdleTimeMillis = 300000
#用來檢測連線是否有效的sql,要求是一個查詢語句
druid.validationQuery = SELECT 1 FROM DUAL
#申請連線的時候檢測
druid.testWhileIdle =true
#申請連線時執行validationQuery檢測連線是否有效,配置為true會降低效能
druid.testOnBorrow = false
#歸還連線時執行validationQuery檢測連線是否有效,配置為true會降低效能
druid.testOnReturn = false
#開啟PSCache,並且指定每個連線上PSCache的大小
druid.poolPreparedStatements = true
druid.maxPoolPreparedStatementPerConnectionSize = 20
# 屬性型別是字串,通過別名的方式配置擴充套件外掛,常用的外掛有: 監控統計stat 日誌用的log4j 防禦SQL注入的wall
druid.filters =stat,config
# 解密密碼必須要配置的項 config, stat啟用監控過濾器
# druid.connectionProperties=config.decrypt\=true
UserNameFindServlet.java
package com.tingcream.springJdbc.web;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.jdbc.core.JdbcTemplate;
import com.alibaba.fastjson.JSON;
import com.tingcream.springJdbc.common.SpringContextHelper;
/**
* 查詢所有使用者名稱字列表 servlet
* @author jelly
*/
@WebServlet("/userNameFindServlet")
public class UserNameFindServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//從spring容器中獲取bean
JdbcTemplate jdbcTemplate= SpringContextHelper.getBean("jdbcTemplate", JdbcTemplate.class);
String sql="select name from t_user";
List<String> nameList= jdbcTemplate.queryForList(sql, String.class);
// System.out.println(nameList);
//輸出json
response.getWriter().write(JSON.toJSONString(nameList));
}
}
SpringContextHelper.java
package com.tingcream.springJdbc.common;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring 上下文輔助類
* @author jelly
*
*/
@Component
public class SpringContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextHelper.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
public static Object getBean(String name){
return applicationContext.getBean(name);
}
/**
* 從spring 上下文中獲取bean
* @param name
* @param requiredClass
* @return
*/
public static <T> T getBean(String name, Class<T> requiredClass){
return applicationContext.getBean(name, requiredClass);
}
public static <T> T getBean(Class<T> requiredType){
return applicationContext.getBean(requiredType);
}
}
其他測試程式碼 JdbcTemplateTest2.java
package com.tingcream.springJdbc.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.tingcream.springJdbc.model.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/spring.xml"})
public class JdbcTemplateTest2 {
@Resource
private JdbcTemplate jdbcTemplate ;
/**
* queryForObject 統計資料庫中使用者總數
*/
@Test
public void test1(){
String sql="select count(*) from t_user";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println("使用者總數為:"+count);
}
/**
*queryForList 查詢所有使用者名稱字的列表
*/
@Test
public void test2(){
String sql="select name from t_user";
List<String> nameList= jdbcTemplate.queryForList(sql, String.class);
System.out.println(nameList);
}
/**
* query 查詢使用者列表,使用BeanPropertyRowMapper 封裝對映row
*/
@Test
public void test3(){
//String sql="select * from t_user where age>?"; //ok
String sql="select id,name,age from t_user where age>?";//ok
RowMapper<User> rowMapper = new BeanPropertyRowMapper<User>(User.class);
List<User> list = jdbcTemplate.query(sql, rowMapper,new Object[]{20});
System.out.println(list);
}
/**
* queryForMap 查詢返回一個封裝map(而不是封裝bean)
*/
@Test
public void test4(){
String sql="select * from t_user where id=?"; //ok
Map<String,Object> map= jdbcTemplate.queryForMap(sql,new Object[]{2});
System.out.println(map);
}
/**
* queryForList 查詢返回一個List<Map<String,Object>>
*/
@Test
public void test5(){
String sql="select * from t_user where age>?"; //ok
List<Map<String,Object>> list =jdbcTemplate.queryForList(sql,new Object[]{20});
System.out.println(list);
}
/**
* batchUpdate 批量插入
*/
@Test
public void test6(){
String sql ="INSERT INTO t_user(`name`,sex,age,city,`describe`) VALUES(?,?,?,?,?)";
List<Object[]> batchArgs =new ArrayList<Object[]>();
batchArgs.add(new Object[]{"張小明",1,22,"杭州","xxx"});
batchArgs.add(new Object[]{"李小華",1,23,"廈門","xxx"});
batchArgs.add(new Object[]{"王小虎",1,28,"株洲","xxx"});
int[] counts= jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(counts);// [1,1,1]
}
}