不用Spring如何正确使用Druid连接池数据源

阿里巴巴的开源数据库连接池工具Druid数据源,在实际使用的时候,通常会和Spring或SpringBoot整合一起使用。

但有些时候如果不用使用Spring或SpringBoot,而直接使用Druid的原生API来操作数据库的话,该如何正确使用呢?

下面是一个使用Druid连接池简单操作数据库的工具类,重点关注Druid数据源的创建和复用:

  1 /**
  2  * 数据库操作工具类
  3  *
  4  * @author shiyanjun
  5  * @since 2020/01/05
  6  */
  7 @Slf4j
  8 public class DbUtil {
  9     private static final String DB_URL = "jdbc:mysql://localhost:3306/authapi"; // 数据库连接URL
 10     private static final String DB_USERNAME = "root"; // 数据库用户名
 11     private static final String DB_PASSWORD = "123456"; // 数据库密码
 12 
 13     // Druid数据源,全局唯一(只创建一次)
 14     private static DruidDataSource druidDataSource;
 15 
 16     /**
 17      * 执行SQL更新
 18      *
 19      * @param updateSql
 20      * @throws SQLException
 21      */
 22     public static void insert(String updateSql) throws SQLException {
 23         Connection connection = null;
 24         Statement statement = null;
 25         ResultSet resultSet = null;
 26         try {
 27             connection = getDruidConnection();
 28             statement = connection.createStatement();
 29             int count = statement.executeUpdate(updateSql);
 30             log.info(">>>>>>>>>>>>> 插入数据 {}", count);
 31         } finally {
 32             // 切记!!! 一定要释放资源
 33             closeResource(connection, statement, resultSet);
 34         }
 35     }
 36 
 37     /**
 38      * 执行SQL查询
 39      *
 40      * @param querySql
 41      * @return
 42      * @throws Exception
 43      */
 44     public static List<Map<String, Object>> executeQuery(String querySql) throws Exception {
 45         List<Map<String, Object>> resultList = new ArrayList<>();
 46         Connection connection = null;
 47         Statement statement = null;
 48         ResultSet resultSet = null;
 49         try {
 50             connection = getDruidConnection();
 51             statement = connection.createStatement();
 52             resultSet = statement.executeQuery(querySql);
 53             ResultSetMetaData metaData = resultSet.getMetaData();
 54             while (resultSet.next()) {
 55                 int columnCount = metaData.getColumnCount();
 56                 Map<String, Object> resultMap = new LinkedHashMap<>();
 57                 for (int i = 1; i <= columnCount; i++) {
 58                     String columnName = metaData.getColumnName(i);// 字段名称
 59                     Object columnValue = resultSet.getObject(columnName);// 字段值
 60                     resultMap.put(columnName, columnValue);
 61                 }
 62                 resultList.add(resultMap);
 63             }
 64             log.info(">>>>>>>>>>>> 查询数据:{}", resultList);
 65         } finally {
 66             // 切记!!! 一定要释放资源
 67             closeResource(connection, statement, resultSet);
 68         }
 69         return resultList;
 70     }
 71 
 72     /**
 73      * 获取Druid数据源
 74      *
 75      * @return
 76      * @throws SQLException
 77      */
 78     private static DruidDataSource getDruidDataSource() throws SQLException {
 79         // 保证Druid数据源在多线程下只创建一次
 80         if (druidDataSource == null) {
 81             synchronized (DbUtil.class) {
 82                 if (druidDataSource == null) {
 83                     druidDataSource = createDruidDataSource();
 84                     return druidDataSource;
 85                 }
 86             }
 87         }
 88         log.info(">>>>>>>>>>> 复用Druid数据源:url={}, username={}, password={}",
 89                 druidDataSource.getUrl(), druidDataSource.getUsername(), druidDataSource.getPassword());
 90         return druidDataSource;
 91     }
 92 
 93     /**
 94      * 创建Druid数据源
 95      *
 96      * @return
 97      * @throws SQLException
 98      */
 99     private static DruidDataSource createDruidDataSource() throws SQLException {
100         DruidDataSource druidDataSource = new DruidDataSource();
101         druidDataSource.setUrl(DB_URL);
102         druidDataSource.setUsername(DB_USERNAME);
103         druidDataSource.setPassword(DB_PASSWORD);
104 
105         /*----下面的具体配置参数自己根据项目情况进行调整----*/
106         druidDataSource.setMaxActive(20);
107         druidDataSource.setInitialSize(1);
108         druidDataSource.setMinIdle(1);
109         druidDataSource.setMaxWait(60000);
110 
111         druidDataSource.setValidationQuery("select 1 from dual");
112 
113         druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
114         druidDataSource.setMinEvictableIdleTimeMillis(300000);
115 
116         druidDataSource.setTestWhileIdle(true);
117         druidDataSource.setTestOnBorrow(false);
118         druidDataSource.setTestOnReturn(false);
119 
120         druidDataSource.setPoolPreparedStatements(true);
121         druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
122 
123         druidDataSource.init();
124         log.info(">>>>>>>>>>> 创建Druid数据源:url={}, username={}, password={}",
125                 druidDataSource.getUrl(), druidDataSource.getUsername(), druidDataSource.getPassword());
126         return druidDataSource;
127     }
128 
129     /**
130      * 获取Druid连接
131      *
132      * @return
133      * @throws SQLException
134      */
135     private static DruidPooledConnection getDruidConnection() throws SQLException {
136         DruidDataSource druidDataSource = getDruidDataSource();
137         DruidPooledConnection connection = druidDataSource.getConnection();
138         return connection;
139     }
140 
141     /**
142      * 释放资源
143      *
144      * @param connection
145      * @param statement
146      * @param resultSet
147      * @throws SQLException
148      */
149     private static void closeResource(Connection connection,
150                                       Statement statement, ResultSet resultSet) throws SQLException {
151         // 注意资源释放顺序
152         if (resultSet != null) {
153             resultSet.close();
154         }
155         if (statement != null) {
156             statement.close();
157         }
158         if (connection != null) {
159             connection.close();
160         }
161     }
162 }

 

一个简单的测试类,模拟多线程向数据库表中插入1w条数据:

 1 import java.text.SimpleDateFormat;
 2 import java.util.Date;
 3 import java.util.UUID;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.Executors;
 6 
 7 /**
 8  * CREATE TABLE `auth_code` (
 9  * `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
10  * `auth_code` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '授权码',
11  * `status` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT '1' COMMENT '状态',
12  * `remark` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '备注',
13  * `create_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期',
14  * `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改日期',
15  * PRIMARY KEY (`id`)
16  * ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin1;
17  */
18 public class AppTest {
19     private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
20     private static ExecutorService executorService = Executors.newCachedThreadPool();// 线程池
21 
22     public static void main(String[] args) throws Exception {
23         String INSERT_SQL = "INSERT INTO `authapi`.`auth_code` " +
24                 "(`auth_code`, `status`, `remark`, `create_date`, `update_time`) VALUES ('%s',%s,'%s','%s','%s')";
25         // 模拟多线程向数据库插入1万条数据
26         for (int i = 0; i < 10000; i++) {
27             Thread.sleep(5);
28             String code = UUID.randomUUID().toString().replaceAll("-", "");
29             String dateStr = dateFormat.format(new Date());
30             String formatSql = String.format(INSERT_SQL, code, i, code, dateStr, dateStr);
31             executorService.execute(() -> {
32                 try {
33                     DbUtil.insert(formatSql);
34                 } catch (Exception e) {
35                     e.printStackTrace();
36                 }
37             });
38         }
39     }
40 }

 

posted @ 2020-01-05 22:22  xuebusi  阅读(2967)  评论(0编辑  收藏  举报