zoukankan      html  css  js  c++  java
  • 不用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 }
  • 相关阅读:
    spring 事务管理
    snmp4j 异步获取节点信息
    snmp4j 过滤错误的节点
    国际化支持
    通过Java反射机制获取对象的方法
    jdk中有哪些包不用自动导入
    位运算符
    spring 从入门到精通 (一)
    命令行工具nslookup查域名DNS服务器
    java/php DES/CBC/PKCS5Padding加密解密算法实现过程
  • 原文地址:https://www.cnblogs.com/jun1019/p/12153928.html
Copyright © 2011-2022 走看看