JDBC基础入门(1)

JDBC(Java Database Connectivity)代表Java编程语言与数据库连接的标准API,然而JDBC只是接口,JDBC驱动才是真正的接口实现,没有驱动无法完成数据库连接. 每个数据库厂商都有自己的驱动,用来连接自己公司的数据库(如Oricle, MySQL, DB2, MS SQLServer).

下面我们以MySQL为例,JDBC编程大致步骤如下:

/**
 * @author jifang
 * @since 16/2/18 上午9:02.
 */
public class SQLClient {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        /* 加载数据库驱动 */
        Class.forName("com.mysql.jdbc.Driver");
        /* 通过 DriverManager 获取数据库连接 */
        Connection connection = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
        /* 通过 Connection 创建 Statement */
        Statement statement = connection.createStatement();
        /* 通过 Statement 执行SQL */
        ResultSet users = statement.executeQuery("SELECT * FROM user");
        /* 操作 ResultSet 结果集 */
        int columnCount = users.getMetaData().getColumnCount();
        while (users.next()) {
            for (int i = 1; i <= columnCount; ++i) {
                System.out.printf("%s\t", users.getObject(i));
            }
            System.out.println();
        }
        /* 回收数据库资源(推荐使用Java1.7提供的 可以自动关闭资源的try) */
        users.close();
        statement.close();
        connection.close();
    }
}

注意: 需要在pom.xml中添加如下MySQL驱动:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.36</version>
</dependency>

注: ResultSet参数columnIndex索引从1开始,而不是0!

ConnectionManger

DriverManger

JDBC规定: 驱动类在被加载时,需要主动把自己注册到DriverManger中:

com.mysql.jdbc.Driver

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

代码显示:只要去加载com.mysql.jdbc.Driver类那么就会执行static块, 从而把com.mysql.jdbc.Driver注册到DriverManager中.

java.sql.DriverManager是用于管理JDBC驱动的服务类,其主要功能是获取Connection对象:

1. static Connection getConnection(String url, Properties info)

2. static Connection getConnection(String url, String user, String password)

另: 还可以在获取Connection的URL中设置参数,如: jdbc:mysql://host:port/database?useUnicode=true&characterEncoding=UTF8

useUnicode=true&characterEncoding=UTF8指定连接数据库的过程中使用Unicode字符集/UTF-8编码;

Connection

java.sql.Connection代表数据库连接,每个Connection代表一个物理连接会话, 该接口提供如下创建Statement的方法, 只有获取Statement之后才可执行SQL语句:

Creates a Statement object for sending SQL statements to the database.

其中Connection还提供了如下控制事务/保存点的方法:

Creates a savepoint with the given name in the current transaction and returns the new Savepoint object that represents it.

以上方法还存在不同的重载形式, 详细可参考JDK文档.

ConnectionManger

由于获取Connection的步骤单一,每次可能只是加载的参数不同,因此我们可以将获取Connection的操作封装成一个方法,并使其从配置文件中加载配置:

配置文件形式

## Data Source
mysql.driver.class=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://host:port/database
mysql.user=admin
mysql.password=admin
ConnectionManger
/**
 * @author jifang
 * @since 16/2/19 上午10:40.
 */
public class ConnectionManger {
    /*获取原生Connection*/
    public static Connection getConnection(String file) {
        Properties config = SQLUtil.loadConfig(file);
        try {
            Class.forName(config.getProperty("mysql.driver.class"));
            String url = config.getProperty("mysql.url");
            String username = config.getProperty("mysql.user");
            String password = config.getProperty("mysql.password");
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}
SQLUtil
/**
 * @author jifang
 * @since 16/2/18 上午8:24.
 */
public class SQLUtil {
    /**
     * 加载.properties配置文件
     *
     * @param file
     * @return
     */
    public static Properties loadConfig(String file) {
        Properties properties = new Properties();
        try {
            properties.load(ClassLoader.getSystemResourceAsStream(file));
            return properties;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

数据库连接池

前面通过DriverManger获得Connection, 一个Connection对应一个实际的物理连接,每次操作都需要打开物理连接, 使用完后立即关闭;这样频繁的打开/关闭连接会造成不必要的数据库系统性能消耗.

数据库连接池提供的解决方案是:当应用启动时,主动建立足够的数据库连接,并将这些连接组织成连接池,每次请求连接时,无须重新打开连接,而是从池中取出已有连接,使用完后并不实际关闭连接,而是归还给池.

JDBC数据库连接池使用javax.sql.DataSource表示, DataSource只是一个接口, 其实现通常由服务器提供商(如WebLogic, WebShere)或开源组织(如DBCP,C3P0和HikariCP)提供.

数据库连接池的常用参数如下:

数据库初始连接数;

连接池最大连接数;

连接池最小连接数;

连接池每次增加的容量;

C3P0

Tomcat默认使用的是DBCP连接池,但相比之下,C3P0则比DBCP更胜一筹(hibernate推荐使用C3P0),C3P0不仅可以自动清理不再使用的Connection, 还可以自动清理Statement/ResultSet, 使用C3P0需要在pom.xml中添加如下依赖:

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>mchange-commons-java</artifactId>
    <version>0.2.11</version>
</dependency>
ConnectionManger
public class ConnectionManger {
    /*双重检测锁保证DataSource单例*/
    private static DataSource dataSource;
    /*获取DataSource*/
    public static DataSource getDataSourceC3P0(String file) {
        if (dataSource == null) {
            synchronized (ConnectionManger.class) {
                if (dataSource == null) {
                    Properties config = SQLUtil.loadConfig(file);
                    try {
                        ComboPooledDataSource source = new ComboPooledDataSource();
                        source.setDriverClass(config.getProperty("mysql.driver.class"));
                        source.setJdbcUrl(config.getProperty("mysql.url"));
                        source.setUser(config.getProperty("mysql.user"));
                        source.setPassword(config.getProperty("mysql.password"));
                        // 设置连接池最大连接数
                        source.setMaxPoolSize(Integer.valueOf(config.getProperty("pool.max.size")));
                        // 设置连接池最小连接数
                        source.setMinPoolSize(Integer.valueOf(config.getProperty("pool.min.size")));
                        // 设置连接池初始连接数
                        source.setInitialPoolSize(Integer.valueOf(config.getProperty("pool.init.size")));
                        // 设置连接每次增量
                        source.setAcquireIncrement(Integer.valueOf(config.getProperty("pool.acquire.increment")));
                        // 设置连接池的缓存Statement的最大数
                        source.setMaxStatements(Integer.valueOf(config.getProperty("pool.max.statements")));
                        // 设置最大空闲时间
                        source.setMaxIdleTime(Integer.valueOf(config.getProperty("pool.max.idle_time")));
                        dataSource = source;
                    } catch (PropertyVetoException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return dataSource;
    }
    /*获取Connection*/
    public static Connection getConnectionC3P0(String file) {
        return getConnection(getDataSourceC3P0(file));
    }
    public static Connection getConnection(DataSource dataSource) {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    // ...
}

C3P0还可以使用配置文件来初始化连接池(配置文件可以是properties/XML, 在此仅介绍XML),C3P0配置文件名必须为c3p0-config.xml,其放在类路径下:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="jdbcUrl">jdbc:mysql://host:port/database</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">user</property>
        <property name="password">password</property>
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">3</property>
        <property name="maxPoolSize">20</property>
    </default-config>
    <named-config name="mysql-config">
        <property name="jdbcUrl">jdbc:mysql://host:port/common</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">user</property>
        <property name="password">password</property>
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">3</property>
        <property name="maxPoolSize">20</property>
    </named-config>
</c3p0-config>

这样, 我们在创建ComboPooledDataSource时就默认加载配置文件中的配置, 无须手动配置:

public static DataSource getDataSourceC3P0(String file) {
    if (dataSource == null) {
        synchronized (ConnectionManger.class) {
            if (dataSource == null) {
                dataSource = new ComboPooledDataSource();
            }
        }
    }
    return dataSource;
}

C3P0配置文件可以配置多个连接信息, 并为每个配置命名, 这样可以方便的通过配置名称来切换配置信息:

public static DataSource getDataSourceC3P0(String file) {
    if (dataSource == null) {
        synchronized (ConnectionManger.class) {
            if (dataSource == null) {
                dataSource = new ComboPooledDataSource("mysql-config");
            }
        }
    }
    return dataSource;
}

本文分享自微信公众号 - Java帮帮(javahelp)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2016-12-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java并发学习5【面试+工作】

    future模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用。当我们需要调用一个函数方法时,如果这个函数执行很慢,那么我们就要进行等待。但有时候...

    Java帮帮
  • MySQL分表3种方法【面试+工作】

    MySQL 分表3种方法 摘要: 当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会卡在那儿了,那么分表的目的就在于此,减...

    Java帮帮
  • cmd命令窗口连接mysql的命令大全

    连接:mysql -h主机地址 -u用户名 -p用户密码 (注:u与root可以不用加空格,其它也一样) 断开:exit (回车)

    Java帮帮
  • Github 项目推荐 | Basel Face Model 2017 完全参数化人脸

    本软件可以从 Basel Face Model 2017 里生成完全参数化的人脸,论文链接: https://arxiv.org/abs/1712.01619 ...

    AI研习社
  • PHP分页原理

    <?php $conn=@mysql_connect(“localhost”,”root”,”123456″) or die(“数据库连接失败”); $se...

    苦咖啡
  • eclipse工具下hadoop环境搭建

    eclipse工具下hadoop环境搭建:     window10操作系统中搭建eclipse64开发系统,配置hadoop的eclipse插件,让eclip...

    别先生
  • [javaEE] 开源数据库连接池

    apache提供的连接池实现,需要导入common-dbcp.jar commons-pool.jar

    陶士涵
  • H3C的CAS3.0系统下Windows Server 2008 R2 Standard版增加内存的方法

    版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

    耕耘实录
  • 如何在Linux中设置快捷方式图标

    Linux系统下创建快捷方式可以更快地打开应用。这里给大家介绍了一种方法,也是之前查了些资料整理的,跟大家分享一下。

    砸漏
  • CheckStyle学习笔记

    CheckStyle是SourceForge下的一个项目,提供了一个帮助JAVA开发人员遵守某些编码规范的工具。它能够自动化代码规范检查过程,从而使得开发人员从...

    程序员_备忘录

扫码关注云+社区

领取腾讯云代金券