3-JDBC(Java数据库连接)

1. JDBC(Java数据库连接)

(1).原理

  • ①,装载数据库驱动程序;
  • ②,通过jdbc建立数据库连接;
  • ③,访问数据库,执行sql语句;
  • ④,断开数据库连接。

    (2).代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* JDBC原理的简单实现
*/
public class FindAllUsers {

public static void main(String[] args) throws Exception{
// 0.初始化数据库连接对象等信息
final String USERNAME = "root";
final String PASSWORD = "111111";
final String DRIVERCLASS = "com.mysql.jdbc.Driver";
final String URL = "jdbc:mysql://localhost:3306/imooclog";

// 1.加载数据库驱动
// 获得字符串参数中指定的类,并初始化该类;将Driver类获取出来
Class.forName(DRIVERCLASS);
// 2.通过jdbc获取数据库的连接
Connection conn = DriverManager.getConnection(URL,USERNAME,PASSWORD);
// 3.编写sql语句
String sql = "select * from person";
// 4.创建预编译对象,并将写好的sql语句 传递给预编译对象
PreparedStatement pstmt = conn.prepareStatement(sql);
// 5.执行查询语句并返回结果给ResultSet
ResultSet result = pstmt.executeQuery();
// 6.输出查询结果
while(result.next()){
// 根据数据表中的字段名将整列的数据取出来
System.out.println(result.getString("id")+","+result.getString("name"));
}
// 7.断开数据库的连接
result.close();
pstmt.close();
conn.close();
}
}

(3).分析

​ 程序开发过程中,存在很多问题:首先,每一次web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。

​ 那么此时的数据库连接就是非常稀缺的资源,那么可以采用数据库连接池的方式来对连接进行妥善管理。其实我们查询完数据库后,如果不关闭连接,而是暂时存放起来,当别人使用时,把这个连接给他们使用。就避免了一次建立数据库连接和断开的操作时间消耗。

​ 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。

(4).常见的数据库连接池

  • Druid (目前更新活跃)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    url:jdbc:mysql://localhost:3306/mydb
    driverClassName:com.mysql.jdbc.Driver
    username:root
    password:aaaaaaaa

    filters:stat

    maxActive:20
    initialSize:1
    maxWait:60000
    minIdle:10
    # maxIdle:15

    timeBetweenEvictionRunsMillis:60000
    minEvictableIdleTimeMillis:300000

    validationQuery:SELECT 'x'
    testWhileIdle:true
    testOnBorrow:false
    testOnReturn:false
    # poolPreparedStatements:true
    maxOpenPreparedStatements:20
    • 代码测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    package com.whyun.util.db;

    import javax.sql.DataSource;

    import org.apache.commons.dbcp.BasicDataSourceFactory;

    import com.alibaba.druid.pool.DruidDataSourceFactory;
    import com.whyun.util.config.MySqlConfigProperty;
    import com.whyun.util.config.MySqlConfigProperty2;
    import com.whyun.util.db.source.AbstractDataSource;
    import com.whyun.util.db.source.impl.DbcpSourceMysql;
    import com.whyun.util.db.source.impl.DruidSourceMysql;
    import com.whyun.util.db.source.impl.DruidSourceMysql2;

    // TODO: Auto-generated Javadoc
    /**
    * The Class DataSourceUtil.
    */
    public class DataSourceUtil {

    /** 使用配置文件dbconfig.properties构建Druid数据源. */
    public static final int DRUID_MYSQL_SOURCE = 0;

    /** The duird mysql source. */
    private static DataSource duirdMysqlSource;

    /** 使用配置文件dbconfig2.properties构建Druid数据源. */
    public static final int DRUID_MYSQL_SOURCE2 = 1;

    /** The druid mysql source2. */
    private static DataSource druidMysqlSource2;

    /** 使用配置文件dbconfig.properties构建Dbcp数据源. */
    public static final int DBCP_SOURCE = 4;

    /** The dbcp source. */
    private static DataSource dbcpSource;

    /**
    * 根据类型获取数据源.
    *
    * @param sourceType 数据源类型
    * @return druid或者dbcp数据源
    * @throws Exception the exception
    * @NotThreadSafe
    */
    public static final DataSource getDataSource(int sourceType)
    throws Exception {
    DataSource dataSource = null;
    switch(sourceType) {
    case DRUID_MYSQL_SOURCE:

    if (duirdMysqlSource == null) {
    duirdMysqlSource = DruidDataSourceFactory.createDataSource(
    MySqlConfigProperty.getInstance().getProperties());
    }
    dataSource = duirdMysqlSource;
    break;
    case DRUID_MYSQL_SOURCE2:
    if (druidMysqlSource2 == null) {
    druidMysqlSource2 = DruidDataSourceFactory.createDataSource(
    MySqlConfigProperty2.getInstance().getProperties());
    }
    dataSource = druidMysqlSource2;
    break;
    case DBCP_SOURCE:
    if (dbcpSource == null) {
    dbcpSource = BasicDataSourceFactory.createDataSource(
    MySqlConfigProperty.getInstance().getProperties());
    }
    dataSource = dbcpSource;
    break;
    }
    return dataSource;
    }

    /**
    * 根据数据库类型标示获取DataSource对象,跟{@link com.whyun.util.db.DataSourceUtil#getDataSource(int)}
    * 不同的是,这里DataSource获取的时候使用了单体模式
    *
    * @param sourceType 数据源类型
    * @return 获取到的DataSource对象
    * @throws Exception the exception
    */
    public static final DataSource getDataSource2(int sourceType) throws Exception {

    AbstractDataSource abstractDataSource = null;
    switch(sourceType) {
    case DRUID_MYSQL_SOURCE:
    abstractDataSource = DruidSourceMysql.getInstance();
    break;
    case DRUID_MYSQL_SOURCE2:
    abstractDataSource = DruidSourceMysql2.getInstance();
    break;
    case DBCP_SOURCE:
    abstractDataSource = DbcpSourceMysql.getInstance();
    break;
    }
    return abstractDataSource == null ?
    null :
    abstractDataSource.getDataSource();
    }
    }
  • c3p0(之前使用过,但目前没更新)

    • c3p0-config.xml

      名称必须为”c3p0-config.xml”,必须放在src目录下,c3p0包会默认加载src目录下的c3p0-config.xml文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    <!-- 这是默认配置信息 -->
    <default-config>
    <!-- 连接四大参数配置 -->
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbctest</property>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="user">root</property>
    <property name="password">root</property>
    <!-- 池参数配置 -->
    <property name="acquireIncrement">3</property>
    <property name="initialPoolSize">10</property>
    <property name="minPoolSize">2</property>
    <property name="maxPoolSize">10</property>
    </default-config>

    <!-- 专门为oracle提供的配置信息 -->
    <named-config name="oracle-config">
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="user">root</property>
    <property name="password">123</property>
    <property name="acquireIncrement">3</property>
    <property name="initialPoolSize">10</property>
    <property name="minPoolSize">2</property>
    <property name="maxPoolSize">10</property>
    </named-config>
    </c3p0-config>
    • JDBCUtil工具类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    package com.test.uitls;

    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import javax.sql.DataSource;
    import com.mchange.v2.c3p0.ComboPooledDataSource;

    public class JDBCUtil {
    // 初始化DataSource对象的时候是: ComboPooledDataSource
    private static DataSource ds = new ComboPooledDataSource();

    // 通过 DataSource 获取连接池
    public static DataSource getDataSource() {
    return ds;
    }

    // 获取连接
    public static Connection getConnection() throws SQLException {
    return ds.getConnection();
    }

    /**
    * 关闭连接
    * @param resultSet
    * @param pst
    * @param connection
    */
    public static void close(ResultSet resultSet, PreparedStatement pst, Connection connection) {
    if (resultSet != null) {
    try {
    resultSet.close();
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }
    if (pst != null) {
    try {
    pst.close();
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }
    if (connection != null) {
    try {
    connection.close();
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }
    }

    }
    • 数据库查询操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    package com.test.dao;

    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import com.test.uitls.JDBCUtil;

    public class JDBCDao {
    /**
    *  * 增加,删除,修改  
    */
    public static void insertOrDeleteOrUpdate(String sql) {
    try {
    Connection connection = JDBCUtil.getConnection();
    PreparedStatement pst = connection.prepareStatement(sql);
    int execute = pst.executeUpdate();
    System.out.println("执行语句:" + sql + "," + execute + "行数据受影响");
    JDBCUtil.close(null, pst, connection);
    } catch (SQLException e) {
    System.out.println("异常提醒:" + e);
    }
    }

    /**
    *  * 查询,返回结果集  
    */
    public static List<Map<String, Object>> select(String sql) {
    List<Map<String, Object>> returnResultToList = null;
    try {
    Connection connection = JDBCUtil.getConnection();
    PreparedStatement pst = connection.prepareStatement(sql);
    ResultSet resultSet = pst.executeQuery();
    // returnResultToList = returnResultToList(resultSet);
    JDBCUtil.close(resultSet, pst, connection);
    } catch (SQLException e) {

    System.out.println("异常提醒:" + e);
    }
    return returnResultToList;
    }

    /**
    *  * 数据返回集合  * @param resultSet  * @return  * @throws SQLException  
    */
    public static List<Map<String, Object>> returnResultToList(ResultSet resultSet) {
    List<Map<String, Object>> values = null;
    try {
    // 键: 存放列的别名, 值: 存放列的值.
    values = new ArrayList<>();
    // 存放字段名
    List<String> columnName = new ArrayList<>();
    ResultSetMetaData rsmd = resultSet.getMetaData();
    for (int i = 0; i < rsmd.getColumnCount(); i++) {
    // 字段名
    columnName.add(rsmd.getColumnLabel(i + 1));
    }

    System.out.println("表字段为:");
    System.out.println(columnName);
    System.out.println("表数据为:");
    Map<String, Object> map = null;
    // 处理 ResultSet, 使用 while 循环
    while (resultSet.next()) {
    map = new HashMap<>();
    for (String column : columnName) {
    Object value = resultSet.getObject(column);
    map.put(column, value);
    System.out.print(value + "\t");
    }
    // 把一条记录的 Map 对象放入准备的 List 中
    values.add(map);
    System.out.println();
    }
    } catch (SQLException e) {
    System.out.println("异常提醒:" + e);
    }
    return values;
    }
    }
  • Apache commons-dbcp

  • HikariCP

-------------本文结束感谢您的阅读-------------
我们都只是大自然的搬运工!
0%