0
点赞
收藏
分享

微信扫一扫

JDBC基础入门(1)

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

JDBC基础入门(1)_sql

下面我们以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语句:


方法

描述

​Statement createStatement()​

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

​PreparedStatement prepareStatement(String sql)​

Creates a PreparedStatement object for sending parameterized SQL statements to the database.

​CallableStatement prepareCall(String sql)​

Creates a CallableStatement object for calling database stored procedures.

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


方法

描述

​Savepoint setSavepoint(String name)​

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

​void setTransactionIsolation(int level)​

Attempts to change the transaction isolation level(事务隔离级别) for this Connection object to the one given.

​void setAutoCommit(boolean autoCommit)​

Sets this connection’s auto-commit mode to the given state.

​void rollback()​

Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object.

​void rollback(Savepoint savepoint)​

Undoes all changes made after the given Savepoint object was set.

​void commit()​

Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.

以上方法还存在不同的重载形式, 详细可参考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;

}



举报

相关推荐

0 条评论