MySQL:JDBC基础及连接数据库的方式

文章转载多处:https://blog.csdn.net/weixin_34121282/article/details/93382694

文章目录

一、JDBC基础

  • DBC (Java DB Connection)—Java数据库连接

  • JDBC是一种可用于执行SQL语句的JAVA API(ApplicationProgramming Interface应用程序设计接口)。它由一些Java语言编写的类和界面组成。

  • JDBC为数据库应用开发人员和数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯JAVA语言编写完整的数据库应用程序。

  • JDBC代表JAVA数据库连接。它是一个软件层,允许开发者在JAVA中编写客户端/服务器应用。

(一)ODBC到JDBC的发展历程

ODBC是OpenDatabaseConnectivity的英文简写。它是一种用来在相关或不相关的数据库管理系统(DBMS)中存取数据的,用C语言实现的,标准应用程序数据接口。通过ODBCAPI,应用程序可以存取保存在多种不同数据库管理系统(DBMS)中的数据,而不论每个DBMS使用了何种数据存储格式和编程接口。

1.ODBC的结构模型

ODBC的结构包括四个主要部分:应用程序接口、驱动器管理器、数据库驱动器和数据源。

应用程序接口:屏蔽不同的ODBC数据库驱动器之间函数调用的差别,为用户提供统一的SQL编程接口。

驱动器管理器:为应用程序装载数据库驱动器。

数据库驱动器:实现ODBC的函数调用,提供对特定数据源的SQL请求。如果需要,数据库驱动器将修改应用程序的请求,使得请求符合相关的DBMS所支持的文法。

数据源:由用户想要存取的数据以及与它相关的操作系统、DBMS和用于访问DBMS的网络平台组成。

虽然ODBC驱动器管理器的主要目的是加载数据库驱动器,以便ODBC函数调用,但是数据库驱动器本身也执行ODBC函数调用,并与数据库相互配合。因此当应用系统发出调用与数据源进行连接时,数据库驱动器能管理通信协议。当建立起与数据源的连接时,数据库驱动器便能处理应用系统向DBMS发出的请求,对分析或发自数据源的设计进行必要的翻译,并将结果返回给应用系统。

2.JDBC的诞生

自从Java语言于1995年5月正式公布以来,Java风靡全球。出现大量的用java语言编写的程序,其中也包括数据库应用程序。由于没有一个Java语言的API,编程人员不得不在Java程序中加入C语言的ODBC函数调用。这就使很多Java的优秀特性无法充分发挥,比如平台无关性、面向对象特性等。随着越来越多的编程人员对Java语言的日益喜爱,越来越多的公司在Java程序开发上投入的精力日益增加,对java语言接口的访问数据库的API的要求越来越强烈。也由于ODBC的有其不足之处,比如它并不容易使用,没有面向对象的特性等等,SUN公司决定开发一Java语言为接口的数据库应用程序开发接口。在JDK1.x版本中,JDBC只是一个可选部件,到了JDK1.1公布时,SQL类包(也就是JDBCAPI)就成为Java语言的标准部件。

(二)JDBC技术概述

  1. JDBC是一种可用于执行SQL语句的JavaAPI(ApplicationProgrammingInterface,应用程序设计接口)。通过使用JDBC,开发人员可以很方便地将SQL语句传送给几乎任何一种数据库。也就是说,开发人员可以不必写一个程序访问Sybase,写另一个程序访问Oracle,再写一个程序访问Microsoft的SQLServer。用JDBC写的程序能够自动地将SQL语句传送给相应的数据库管理系统(DBMS)。不但如此,使用Java编写的应用程序可以在任何支持Java的平台上运行,不必在不同的平台上编写不同的应用。Java和JDBC的结合可以让开发人员在开发数据库应用时真正实现“WriteOnce,RunEverywhere!”

  2. Java具有健壮、安全、易用等特性,而且支持自动网上下载,本质上是一种很好的数据库应用的编程语言。它所需要的是Java应用如何同各种各样的数据库连接,JDBC正是实现这种连接的关键。

  3. JDBC扩展了Java的能力,如使用Java和JDBCAPI就可以公布一个Web页,页中带有能访问远端数据库的Ap plet。或者企业可以通过JDBC让全部的职工(他们可以使用不同的操作系统,如Windwos,Machintosh和UNIX)在In tranet上连接到几个全球数据库上,而这几个全球数据库可以是不相同的。随着越来越多的程序开发人员使用Java语言,对Java访问数据库易操作性的需求越来越强烈。

  4. JDBC API定义了一组用于与数据库通信的接口和类。这些接口和类位于java.sql包中。

  5. JDBC是用来(让我们的程序)通过网络来操作数据库的,作用很重要;JDBC技术也是Java核心技术之一。凡是需要用网络操作数据库的程序,JDBC编程有问题,一切都是白搭。

(三)JDBC技术及使用详解

从结构图中可以看出,通过JDBC API 让我们的Java应用程序可以利用JDBCDriver Manager[JDBC驱动管理],连接到JDBC驱动;体现在我们的工程中也就是要导入驱动jar包。

1.何谓驱动?

不同的数据库厂商或者同一厂商的不同数据库版本都会提供不同的驱动,任何应用程序都是通过这个驱动来操作特定厂商、特定版本的数据库的。

2.JDBC驱动程序的分类

  • 第一类JDBC驱动程序是JDBC-ODBC桥再加上一个ODBC驱动程序。这类驱动一般不用现在的编程应用中。

  • 第二类JDBC驱动程序是部分JAVAAPI代码的驱动程序,用于把JDBC调用转换成主流数据库API的本机调用。

  • 第三类JDBC驱动程序是面向数据库中间件的纯JAVA驱动程序,JDBC调用被转换成一种中间件厂商的协议,中间件再把这些调用转换到数据库API。

  • 第四类JDBC驱动程序是直接面向数据库的纯JAVA驱动程序。

二、JDBC连接MySQL数据库的基础方式

(一)通过JDBC操作数据库的基本步骤

  • 第1步:注册驱动 (只做一次)

  • 第2步:建立连接(Connection)

  • 第3步:创建执行SQL的语句(Statement)

  • 第4步:执行语句

  • 第5步:处理执行结果(ResultSet)

  • 第6步:释放资源

1.使用JDBC第一步:加载驱动

注册驱动有三种方式:

  • Class.forName(“com.mysql.jdbc.Driver”);推荐这种方式,不会对具体的驱动类产生依赖

  • DriverManager.registerDriver(com.mysql.jdbc.Driver);会对具体的驱动类产生依赖

  • System.setProperty(“jdbc.drivers”, “driver1:driver2”);虽然不会对具体的驱动类产生依赖;但注册不太方便,所以很少使用

2.使用JDBC第二步:建立连接

通过Connection建立连接,Connection是一个接口类,其功能是与数据库进行连接(会话)。

  • 建立Connection接口类对象:

Connection conn =DriverManager.getConnection(url, user, password);

  • URL的格式要求为:

    JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&
    如:"jdbc:mysql://localhost:3306/test“

  • user即为登录数据库的用户名,如root

  • password即为登录数据库的密码,为空就填””

3.使用JDBC第三步:创建执行对象

执行对象Statement负责执行SQL语句,由Connection对象产生。

Statement接口类还派生出两个接口类PreparedStatement和CallableStatement,这两个接口类对象为我们提供了更加强大的数据访问功能。

  • 创建Statement的语法为:

Statement st = conn.createStatement();

4.使用JDBC第四步:执行SQL语句

执行对象Statement提供两个常用的方法来执行SQL语句。

  • executeQuery(Stringsql),该方法用于执行实现查询功能的sql语句,返回类型为ResultSet(结果集)。

如:ResultSet rs =st.executeQuery(sql);

  • executeUpdate(Stringsql),该方法用于执行实现增、删、改功能的sql语句,返回类型为int,即受影响的行数。

如:int flag = st.executeUpdate(sql);

5.使用JDBC第五步:处理执行结果

ResultSet对象

ResultSet对象负责保存Statement执行后所产生的查询结果。

结果集ResultSet是通过游标来操作的。

游标就是一个可控制的、可以指向任意一条记录的指针。有了这个指针我们就能轻易地指出我们要对结果集中的哪一条记录进行修改、删除,或者要在哪一条记录之前插入数据。一个结果集对象中只包含一个游标。

6.使用JDBC 第六步——释放资源

Connection对象的close方法用于关闭连接,并释放和连接相关的资源。

(二)JDBC连接数据库具体代码示例

1.确认数据库是否存在

要查询、增、删数据库,首先得确认在mysql中是否存在数据库及相应的表,可以通过cmd在mysql中进行确认
在这里插入图片描述

2.连接并操作数据库

在这里插入图片描述

    // TODO: 2021/7/8 传统的连接方式
    @Override
    public void connectionByJdbc() throws ClassNotFoundException, IOException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        InputStream resourceAsStream = JdbcConnectionImpl.class.getClassLoader().getResourceAsStream("jdbcproperties/jdbc.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        Connection connection = DriverManager.getConnection(url, user, password);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            System.out.println(resultSet.getString("name"));
            int salary = resultSet.getInt("salary");
            System.out.println(salary);
        }
    }



三、DBCP连接MySQL数据库详解

DBCP(DataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。

DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:

  • commons-dbcp.jar,
  • commons-pool.jar

由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

(一)DBCP2原理

DBCP2在初始化时会从数据库获取指定数量的连接,把这些连接存放到空闲连接队列LinkedBlockingDeque里面,这个队列是双向链路阻塞型队列,先进先出,每次要使用连接时就从这个队列获取头部结点,获取连接时使用的锁是ReentrantLock.获取到连接时,该连接节点出队列,更改状态并且存放到一个ConcurrentHashMap中,标识该连接已被使用,另外会有一个空闲连接检测线程不断去检测ConcurrentHashMap中连接的状态,如果连接已经关闭(不是数据库连接关闭,而是连接在DBCP连接池中关闭),则把它从ConcurrentHashMap中删除,并且回收到LinkedBlockingDeque里面。

  • 优点:
    配置简单
  • 缺点:
    无论是空闲连接还是已使用的连接,都是存放加锁的ConcurrentHashMap或LinkedBlockingDeque中,并发量低,性能不好,适用于小型系统。从数据库获取连接的过程中还加了synchronized同步锁,如果网络容易中断的场景下,一旦与数据库建立的网络出现问题,容易导致死锁。

(二)认识BasicDataSource类

commons-dbcp.jar包中有一个类BasicDataSource类,该类有一个无参构造方法,可以实例化一个BasicDataSource对象,更重要的是这个是实现了DataSource接口,这样更有利于规范化还更符合面向对象接口编程。该类当中有四个必须的set方法和四个重要的拓展方法

1.四个必须的set方法

参数描述
setDriverClassName(String driverClassName)设置驱动名
setUrl(String url)设置url参数
setUsername(String username)设置数据库连接用户名
setPassword(String password)设置数据库连接密码

2.四个重要的拓展方法

参数描述
setMaxActive(int maxActive)最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制.
setInitialSize(int initialSize)初始化连接:连接池启动时创建的初始化连接数量,1.2版本后支持
setMaxIdle(int maxIdle)最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制
setMinIdle(int minIdle)最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建
maxWaitMillis最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常

3.事务属性配置

在这里插入图片描述
数据源连接健康状况检查
在这里插入图片描述
缓存语句
在这里插入图片描述
连接泄露回收
在这里插入图片描述

(三)读取properties文件创建BasicDataSource

1.properties文件格式

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?usessl=false&serverTimezone=UTC
username=root
password=123456

2.用BasicDataSourceFactoy创建BasicDataSource数据库连接池

  @Test
    public void test30() throws Exception {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("jdbcproperties/jdbc.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
        // TODO: 2021/7/8 设置创建数据库连接池时初始的连接数量 
        dataSource.setInitialSize(10);
        // TODO: 2021/7/8 设置最小闲置连接数,如果闲置的连接数小于设定的值,则会自动创建连接 
        dataSource.setMinIdle(2);
        // TODO: 2021/7/8 设置最大闲置连接数量,如果闲置连接数量超过此值,则会释放多余的连接 
        dataSource.setMaxIdle(5);
        // TODO: 2021/7/8 设置最大活动连接数 
        dataSource.setMaxTotal(10);

        Connection connection = dataSource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id =1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            String salary = resultSet.getString("salary");
            System.out.println("Name:" + name + "Salary:" + salary);
        }
    }

(四) 在SpringIOC容器中创建BasicDataSource数据库连接池

1.配置xml核心配置文件

 <!-- TODO:在IOC容器中创建一个BasicDataSource数据库连接池,并将属性数据装配到Bean中,这里的属性与Properties后置处理器配合,解析Bean中
    的属性,产生新的属性名称,并从属性文件中找到对应的属性值,再次传递给BasicDataSource这个bean的属性-->
    <bean id="datasource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.passowrd}"/>
    </bean>

    <!-- TODO:Properties后置处理器,主要用用是解析Bean中的属性,从属性文件中读取对应值,再次传入到Bean中-->
    <!--    <context:property-placeholder location="classpath:dbcp.properties"/>-->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="location" value="classpath:dbcp.properties"/>
    </bean>
    
    <!-- TODO:Spring-jdbc中的数据空间,可将BasicDataSource的Bean封装到其中,可以优化处理-->
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate" autowire="byType"/>

2.测试在IOC容器中BasicDataSource数据库连接池

  • 2.1 第一种测试(基本测试,直接调用的是数据库连接池)
    @Test
    public void test22() throws SQLException {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp.xml");
        BasicDataSource datasource = (BasicDataSource) ac.getBean("datasource");
        Connection connection = datasource.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            int salary = resultSet.getInt("salary");
            System.out.println("姓名为:" + name + ";薪资为:" + salary + ";");
        }
    }
  • 2.2 第二种测试,(调用的是spring-jdbc中的JdbcTemplate的Bean),他是将连接池的Bean注入其中,用他来管理并操作连接池查询、增、删数据,比较方便
  @Test
    public void test47() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) ac.getBean("jdbcTemplate");
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from customer");

        for (Map<String, Object> map : maps) {
            String name = (String) map.get("name");
            Long salary = (Long) map.get("salary");
            System.out.println(name + "=" + salary);
        }
    }

(五)创建BasicDataSource工具类来创建连接池

1.创建DBCP连接池管理工具类

public class BasicDataSourceUtil {

    private static BasicDataSource thisbasicDataSource;

    public BasicDataSource createDataSource() throws IOException {
        BasicDataSource basicDataSource = new BasicDataSource();
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("dbcp2.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        String driverClassName = properties.getProperty("driverClassName");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        basicDataSource.setDriverClassName(driverClassName);
        basicDataSource.setUrl(url);
        basicDataSource.setUsername(username);
        basicDataSource.setPassword(password);
        thisbasicDataSource = basicDataSource;
        return basicDataSource;
    }

    // TODO: 2021/7/9 返回一个dbcp数据为连接池,一般不会采取这样的做法,不安全
    public static BasicDataSource getBaiseDataResouce(){
        return thisbasicDataSource;
    }

    // TODO: 2021/7/9 返回一个连接
    public static Connection getConnection() throws SQLException {
        return thisbasicDataSource.getConnection();
    }
}

在上面的代码中,是通过读取proeperties文件中对应的属性值,然后传递给DBCP数据库连接池对象,我们也可以通过BasicDataSourceFactory工厂,只接加载属性文件对象,这样更快速便捷,只是对Properties文件的格式有一定的要求。要求属性文件中的属性名必须和BasicDataSource中的属性名一致,具体部分属性如下:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&useSSL=false
username=root
password=123456

maxTotal:100
initialSize:10
maxWait:60000
minIdle:10
maxIdle:15

logAbandoned:true
removeAbandoned:true
removeAbandonedTimeout:10
timeBetweenEvictionRunsMillis:10000
numTestsPerEvictionRun:10
minEvictableIdleTimeMillis:10000
validationQuery:SELECT 1 FROM DUAL

#\u6821\u9A8C\u94FE\u63A5
testWhileIdle:true
testOnBorrow:true

2.在静态工厂工具类中采取BasicDataSourceFactory来创建DBCP数据库连接池

在前一小节中,我们采取的是读取属性文件的属性值后,再单独将每个属性值传递给BasicDataSource数据库连接池对象,这样的效率比较慢,在这里,我们可以采取BasicDataSourceFactiory类加载属性对象,来创建一个DBCP数据库连接池。

public class BasicDataSourcePropertiesUtil {

    private static BasicDataSource staticdataSource;
    private static JdbcTemplate staticjdbcTemplate;

    public static BasicDataSource createBasicDataSource(String xmlName) throws Exception {
        InputStream resource AsStream = BasicDataSource.class.getClassLoader().getResourceAsStream(xmlName);
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        staticdataSource = dataSource;
        staticjdbcTemplate = jdbcTemplate;
        return dataSource;
    }

    public static Connection getConnection() throws SQLException {
        return staticdataSource.getConnection();
    }

    public static List<Map<String, Object>> getConnectionQuery(String strQuery) {
        List<Map<String, Object>> maps = staticjdbcTemplate.queryForList(strQuery);
        return maps;
    }
}

针对上的工具类创建的数据库连接池,可通直接调用,也可以通过IOC容器,采取静态工厂的方法来创建.

(1) 直接调用
 @Test
    public void test112() throws Exception {
        BasicDataSource basicDataSource = BasicDataSourcePropertiesUtil.createBasicDataSource("dbcp4.properties");
        List<Map<String, Object>> connectionQuery = BasicDataSourcePropertiesUtil.getConnectionQuery("select * from customer");
        for (Map<String, Object> stringObjectMap : connectionQuery) {
            String name = (String) stringObjectMap.get("name");
            Integer salary = (Integer) stringObjectMap.get("salary");
            System.out.println(name + "=" + salary + ";");
        }
    }
(2) IOC容器中采取静态工厂方式调用
  • 首先得创建IOC容器的xml核心配置文件
   <bean class="util.BasicDataSourcePropertiesUtil" factory-method="createBasicDataSource" id="dataSource">
        <constructor-arg name="xmlName" value="dbcp4.properties"/>
    </bean>
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
  • 创建IOC容器,并从IOC容器中得到DBCP数据库连接池,或者得到JdbcTemplate对象(用于封装DBCP数据库连接池对象BasicDataSource,提供了操作数据库方法)
    @Test
    public void test124() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp4.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) ac.getBean("jdbcTemplate");
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from customer");
        for (Map<String, Object> map : maps) {
            String name = (String) map.get("name");
            Integer salary = (Integer) map.get("salary");
            System.out.println(name + "=" + salary + ";");
        }
    }

3.配置IOC 核心配置文件xml

核心 文件的配置实现了现以下两个功能:

  • 在IOC容器中创建了工具类的一个Bean,做为实例工厂类Bean
  • 调用实例工厂类bean中的方法,在IOC中创建一个BasicDataSource连接池Bean,同时将这个Bean的引用传递到工具类中
    <!-- TODO:创建一个BasicDataSource工具类实例 -->
    <bean id="datasourceutil" class="util.BasicDataSourceUtil"/>
    <!-- TODO:实例工厂类,通过一个方法return 一个BasicDataSource对象,同时在这个实例工厂方法中,将这个数据库连接池的Bean的引用传递给工具类的BasicDataSource的引用 -->
    <bean id="datasource" factory-bean="datasourceutil" factory-method="createDataSource" destroy-method="close"/>

4.分别从IOC容器和工具类中取得BasicDataSource数据库连接池

  • 从IOC中取得连接池
    // TODO: 2021/7/9 这个是从IOC容器中取得到的数据为连接池
    @Test
    public void test44() throws SQLException {
        ApplicationContext ac = new ClassPathXmlApplicationContext("dbcp2.xml");
        BasicDataSource datasource = (BasicDataSource) ac.getBean("datasource");
        Connection newconnection = datasource.getConnection();
        Statement statement = newconnection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            int salary = resultSet.getInt("salary");
            System.out.println("姓名为:" + name + ";薪资为:" + salary + ";");
        }
        resultSet.close();
        statement.close();
        newconnection.close();
    }
  • 从工具类中取得连接池
// TODO: 2021/7/9 调用工具类的做法 ,从工具类中得到数据库连接池
    @Test
    public void test63() throws SQLException {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("dbcp2.xml");
        Connection connection = BasicDataSourceUtil.getConnection();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from customer where id = 1");
        while (resultSet.next()) {
            String name = resultSet.getString("name");
            int salary = resultSet.getInt("salary");
            System.out.println("姓名为:" + name + ";薪资为:" + salary + ";");
        }
        resultSet.close();
        statement.close();
        connection.close();
    }

四、C3P0数据库连接池详解

C3P0,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等,这个被推荐使用.他的配置相对简单,可以直接通过加载文件就可以配置成功!

(一)创建c3p0-config.xml文件

这是一个c3p0数据库连接池的配置文件,他可以默认状态,也可以指定配置名称配置.这样的话,c3p0数据库连接池在创建中,可以指定不同的名,加载一个c3p0-config.xml文件,创建不同的数据库连接池!

  • xml连接池配置文件
<?xml version="1.0" encoding="UTF-8"?>

<!-- TODO: 此文件必须命名为: c3p0-confing.xml-->
<c3p0-config>
    <!-- TODO:此处为给此文件命名为:jdbcConfig,在创建c3p0数据库连接池时,可以通过此名来加载引xml文件 -->
    <named-config name="jdbcConfig">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!-- 当连接数量用尽时,可定期的增量数 -->
        <property name="acquireIncrement">10</property>
        <!-- 数据库初始化时,需要初始化连接池中连接的数量 -->
        <property name="initialPoolSize">100</property>
        <!-- 连接池的最小连接数 -->
        <property name="minPoolSize">10</property>
        <!-- 连接池的最大连接数 -->
        <property name="maxPoolSize">200</property>
        <!-- 连接池中 Statement 的最大个数 -->
        <property name="maxStatements">20</property>
        <!-- 连接池中每个连接可以同时使用的 Statement 的个数 -->
        <property name="maxStatementsPerConnection">5</property>
    </named-config>

    <named-config name="abcd">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!-- 当连接数量用尽时,可定期的增量数 -->
        <property name="acquireIncrement">10</property>
        <!-- 数据库初始化时,需要初始化连接池中连接的数量 -->
        <property name="initialPoolSize">100</property>
        <!-- 连接池的最小连接数 -->
        <property name="minPoolSize">10</property>
        <!-- 连接池的最大连接数 -->
        <property name="maxPoolSize">200</property>
        <!-- 连接池中 Statement 的最大个数 -->
        <property name="maxStatements">20</property>
        <!-- 连接池中每个连接可以同时使用的 Statement 的个数 -->
        <property name="maxStatementsPerConnection">5</property>
    </named-config>
    
    <default-config>
        <!-- TODO:这个地方可以写默认的c3p0数据库连接池配置文件 -->
    </default-config>

</c3p0-config>
  • 直接创建连接池
public class CmoboPoolUtil {

    private static ComboPooledDataSource dataSource;

    public static ComboPooledDataSource createComboPoolDataSource(String c3p0config) {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(c3p0config);
        dataSource = comboPooledDataSource;
        return comboPooledDataSource;
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
}
  • 在IOC容器中以静态工厂的方式创建连接池
?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="datasource" class="util.CmoboPoolUtil" factory-method="createComboPoolDataSource" destroy-method="close">
        <constructor-arg name="c3p0config" value="jdbcConfig"/>
    </bean>
    <bean class="org.springframework.jdbc.core.JdbcTemplate" name="jdbcTemplate">
        <property name="dataSource" ref="datasource"/>
    </bean>

    <bean id="abcd" class="util.CmoboPoolUtil" factory-method="createComboPoolDataSource" destroy-method="close">
        <constructor-arg name="c3p0config" value="abcd"/>
    </bean>
    <bean id="springjdbc" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="abcd"/>
    </bean>


</beans>

(二)采取IOC容器创建C3P0数据库连接池

在IOC容器中,可以直接创建一个C3p0的数据库连接池的Bean,并设置配置属性,配置属性可以创建一个配置属性properties文件,在IOC容器中上,通过properties后置处理器解析c3p0数据库连接池Bean的属性,通过解析的名字,从属性文件中得到对应的属性值,并得新给c3p0数据库连接池中的属性赋值,在这个地方,properties后置处理器的主要功能有:

  • 解析IOC Bean中的属性
  • 加载propertids属性文件
  • 通过解析后的字符找到相应的属性值,并重新赋值给Bean中的属性.

1.c3p0属性文件

driverClass=com.mysql.cj.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost:3306/newdb?useSSL=false&serverTimezone=UTC
user=root
password=123456
acquireIncrement=10
initialPoolSize=100
minPoolSize=10
maxPoolSize=200
maxStatements=20
maxStatementsPerConnection=5

2.IOC容器配置文件xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- TODO:在IOC容器中创建c3p0数据库连接池 -->
    <bean id="c3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${driverClass}"/>
        <property name="jdbcUrl" value="${jdbcUrl}"/>
        <property name="user" value="${user}"/>
        <property name="password" value="${password}"/>

        <property name="acquireIncrement" value="${acquireIncrement}"/>
        <property name="initialPoolSize" value="${initialPoolSize}"/>
        <property name="minPoolSize" value="${minPoolSize}"/>
        <property name="maxPoolSize" value="${maxPoolSize}"/>
        <property name="maxStatements" value="${maxStatements}"/>
        <property name="maxStatementsPerConnection" value="${maxStatementsPerConnection}"/>
    </bean>
    <!-- TODO:IOC后置处理器,解析Bean中的属性,从指定的属性文件中读取对应的属性值,重新注入到Bean中 -->
    <!--    <context:property-placeholder location="classpath:c3p0.properties"/>-->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="location" value="classpath:c3p0.properties"/>
    </bean>
    <!-- TODO:创建一个Srping-jdbc包装类,用于封装c3po数据库连接池,可以对数据库连接池进行操作 -->
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate" autowire="byType"/>

</beans>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值