JDBC DataSource Example – Oracle, MySQL and Apache DBCP Tutorial

We have already seen that JDBC DriverManager can be used to get relational database connections. But when it comes to actual programming, we want more than just connections.

Most of the times we are looking for loose coupling for connectivity so that we can switch databases easily, connection pooling for transaction management and distributed systems support. JDBC DataSource is the preferred approach if you are looking for any of these features in your application. JDBC DataSource interface is present in javax.sql package and it only declare two overloaded methods getConnection() andgetConnection(String str1,String str2).

It is the responsibility of different Database vendors to provide different kinds of implementation of DataSource interface. For example MySQL JDBC Driver provides basic implementation of DataSource interface with com.mysql.jdbc.jdbc2.optional.MysqlDataSource class and Oracle database driver implements it with oracle.jdbc.pool.OracleDataSource class.

These implementation classes provide methods through which we can provide database server details with user credentials. Some of the other common features provided by these DataSource implementation classes are;

  • Caching of PreparedStatement for faster processing
  • Connection timeout settings
  • Logging features
  • ResultSet maximum size threshold

Let’s create a simple JDBC project and learn how to use MySQL and Oracle DataSource basic implementation classes to get the database connection. Our final project will look like below image.

Database Setup

Before we get into our example programs, we need some database setup with table and sample data. Installation of MySQL or Oracle database is out of scope of this tutorial, so I will just go ahead and setup table with sample data.

MySQLSetup.sql

--Create Employee table
CREATE TABLE `Employee` (
  `empId` int(10) unsigned NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- insert some sample data
INSERT INTO `Employee` (`empId`, `name`)
VALUES
    (1, ‘Pankaj‘),
    (2, ‘David‘);

commit;

  

OracleSetup.sql

CREATE TABLE "EMPLOYEE"
  (
    "EMPID"   NUMBER NOT NULL ENABLE,
    "NAME"    VARCHAR2(10 BYTE) DEFAULT NULL,
    PRIMARY KEY ("EMPID")
  );

Insert into EMPLOYEE (EMPID,NAME) values (10,‘Pankaj‘);
Insert into EMPLOYEE (EMPID,NAME) values (5,‘Kumar‘);
Insert into EMPLOYEE (EMPID,NAME) values (1,‘Pankaj‘);
commit;

  

Now let’s move on to our java programs. For having database configuration loosely coupled, I will read them from property file.

db.properties

#mysql DB properties
MYSQL_DB_DRIVER_CLASS=com.mysql.jdbc.Driver
MYSQL_DB_URL=jdbc:mysql://localhost:3306/UserDB
MYSQL_DB_USERNAME=pankaj
MYSQL_DB_PASSWORD=pankaj123

#Oracle DB Properties
ORACLE_DB_DRIVER_CLASS=oracle.jdbc.driver.OracleDriver
ORACLE_DB_URL=jdbc:oracle:thin:@localhost:1521:orcl
ORACLE_DB_USERNAME=hr
ORACLE_DB_PASSWORD=oracle

  

Make sure that above configurations match with your local setup. Also make sure you have MySQL and Oracle DB JDBC jars included in the build path of the project.

JDBC MySQL and Oracle DataSource Example

Let’s write a factory class that we can use to get MySQL or Oracle DataSource.

MyDataSourceFactory.java

package com.journaldev.jdbc.datasource;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import oracle.jdbc.pool.OracleDataSource;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class MyDataSourceFactory {

    public static DataSource getMySQLDataSource() {
        Properties props = new Properties();
        FileInputStream fis = null;
        MysqlDataSource mysqlDS = null;
        try {
            fis = new FileInputStream("db.properties");
            props.load(fis);
            mysqlDS = new MysqlDataSource();
            mysqlDS.setURL(props.getProperty("MYSQL_DB_URL"));
            mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME"));
            mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return mysqlDS;
    }

    public static DataSource getOracleDataSource(){
        Properties props = new Properties();
        FileInputStream fis = null;
        OracleDataSource oracleDS = null;
        try {
            fis = new FileInputStream("db.properties");
            props.load(fis);
            oracleDS = new OracleDataSource();
            oracleDS.setURL(props.getProperty("ORACLE_DB_URL"));
            oracleDS.setUser(props.getProperty("ORACLE_DB_USERNAME"));
            oracleDS.setPassword(props.getProperty("ORACLE_DB_PASSWORD"));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return oracleDS;
    }

}

  

Notice that both Oracle and MySQL DataSource implementation classes are very similar, let’s write a simple test program to use these methods and run some test.

DataSourceTest.java

package com.journaldev.jdbc.datasource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

public class DataSourceTest {

    public static void main(String[] args) {

        testDataSource("mysql");
        System.out.println("**********");
        testDataSource("oracle");

    }

    private static void testDataSource(String dbType) {
        DataSource ds = null;
        if("mysql".equals(dbType)){
            ds = MyDataSourceFactory.getMySQLDataSource();
        }else if("oracle".equals(dbType)){
            ds = MyDataSourceFactory.getOracleDataSource();
        }else{
            System.out.println("invalid db type");
            return;
        }

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            con = ds.getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery("select empid, name from Employee");
            while(rs.next()){
                System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
                try {
                    if(rs != null) rs.close();
                    if(stmt != null) stmt.close();
                    if(con != null) con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
    }

}

  

Notice that the client class is totally independent of any Database specific classes. This helps us in hiding the underlying implementation details from client program and achieve loose coupling and abstraction benefits.

When we run above test program, we will get below output.

Employee ID=1, Name=Pankaj
Employee ID=2, Name=David
**********
Employee ID=10, Name=Pankaj
Employee ID=5, Name=Kumar
Employee ID=1, Name=Pankaj

  

Apache Commons DBCP Example

If you look at above DataSource factory class, there are two major issues with it.

  1. The factory class methods to create the MySQL and Oracle DataSource are tightly coupled with respective driver API. If we want to remove support for Oracle database in future or want to add some other database support, it will require code change.
  2. Most of the code to get the MySQL and Oracle DataSource is similar, the only different is the implementation class that we are using.

Apache Commons DBCP API helps us in getting rid of these issues by providing DataSource implementation that works as an abstraction layer between our program and different JDBC drivers.

Apache DBCP library depends on Commons Pool library, so make sure they both are in the build path as shown in the image.

Here is the DataSource factory class using BasicDataSource that is the simple implementation of DataSource.

DBCPDataSourceFactory.java

package com.journaldev.jdbc.datasource;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;

public class DBCPDataSourceFactory {

    public static DataSource getDataSource(String dbType){
        Properties props = new Properties();
        FileInputStream fis = null;
        BasicDataSource ds = new BasicDataSource();

        try {
            fis = new FileInputStream("db.properties");
            props.load(fis);
        }catch(IOException e){
            e.printStackTrace();
            return null;
        }
        if("mysql".equals(dbType)){
            ds.setDriverClassName(props.getProperty("MYSQL_DB_DRIVER_CLASS"));
            ds.setUrl(props.getProperty("MYSQL_DB_URL"));
            ds.setUsername(props.getProperty("MYSQL_DB_USERNAME"));
            ds.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
        }else if("oracle".equals(dbType)){
            ds.setDriverClassName(props.getProperty("ORACLE_DB_DRIVER_CLASS"));
            ds.setUrl(props.getProperty("ORACLE_DB_URL"));
            ds.setUsername(props.getProperty("ORACLE_DB_USERNAME"));
            ds.setPassword(props.getProperty("ORACLE_DB_PASSWORD"));
        }else{
            return null;
        }

        return ds;
    }
}

  

As you can see that depending on user input, either MySQL or Oracle datasource is created. If you are supporting only one database in the application then you don’t even need these logic. Just change the properties and you can switch from one database server to another. The key point through which Apache DBCP provide abstraction is setDriverClassName() method.

Here is the client program using above factory method to get different types of connection.

ApacheCommonsDBCPTest.java

package com.journaldev.jdbc.datasource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

public class ApacheCommonsDBCPTest {

    public static void main(String[] args) {
        testDBCPDataSource("mysql");
        System.out.println("**********");
        testDBCPDataSource("oracle");
    }

    private static void testDBCPDataSource(String dbType) {
        DataSource ds = DBCPDataSourceFactory.getDataSource(dbType);

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            con = ds.getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery("select empid, name from Employee");
            while(rs.next()){
                System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
                try {
                    if(rs != null) rs.close();
                    if(stmt != null) stmt.close();
                    if(con != null) con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }
    }

}

  

When you run above program, the output will be same as earlier program.

If you look at the DataSource and above usage, it can be done with normal DriverManager too. The major benefit of DataSource is when it’s used within a Context and with JNDI.

With simple configurations we can create a Database Connection Pool that is maintained by the Container itself. Most of the servlet containers such as Tomcat and JBoss provide it’s own DataSource implementation and all we need is to configure it through simple XML based configurations and then use JNDI context lookup to get the DataSource and work with it. This helps us by taking care of connection pooling and management from our application side to server side and thus giving us more time to write business logic for the application.

In next tutorial, we will learn how we can configure DataSource in Tomcat Container and use it in Web Application.

时间: 2025-01-15 14:27:23

JDBC DataSource Example – Oracle, MySQL and Apache DBCP Tutorial的相关文章

jdbc连接oracle时报错 Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableC

错误: Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Communications link failure Last packet sent

Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException:

七月 17, 2014 4:56:01 下午 org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [dispatcher] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemExc

jdbc基础 (五) 连接池与数据源 DBCP以及C3P0的使用

一.连接池的概念和使用 在实际应用开发中,特别是在WEB应用系统中,如果JSP.Servlet或EJB使用JDBC直接访问数据库中的数据,每一次数据访问请求都必须经历建立数据库连接.打开数据库.存取数据和关闭数据库连接等步骤,而连接并打开数据库是一件既消耗资源又费时的工作,如果频繁发生这种数据库操作,系统的性能必然会急剧下降,甚至会导致系统崩溃.数据库连接池技术是解决这个问题最常用的方法. 数据库连接池的主要操作如下: (1)建立数据库连接池对象. (2)按照事先指定的参数创建初始数量的数据库连

Apache DBCP数据库连接池溢出调整

数据库最大连接池溢出是在系统运行中比较常见的一个问题,在开发中,可以通过设置最大连接池的各位为1或者2,就能在开发的时候发现数据库连接没有被释放的情况.不过这个小技巧在hibernate和sping等框架大量使用之后就没什么用了. 数据库连接池溢出的源代码: package test.ffm83.commons.dbcp; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDat

ssm简单的示例整合(eclipse+maven+ssm+oracle/mysql+jquery.js)

开发工具我使用的是eclipse,毕竟从学java开始就用这个,比较熟悉 maven其实就是管理jar包的东西,与普通ssm相比也不用配置其他的xml ssm是spring+springmvc+mybatis(重点的东西) 数据库我两个都试过了,更换数据库只需要改那个properties里的东西就行了 然后把我的目录结构拿出来 其中红框内部的就是我们要写的,对了还有pom.xml 一.我的pom.xml: 1 <project xmlns="http://maven.apache.org/

soapUI使用-DataSource获取oracle库中的参数

soapUI使用-DataSource获取oracle库中的参数 下载mysql和oracle驱动包:http://pan.baidu.com/s/1i3sy1MH 放在Program Files\SmartBear\SoapUI-Pro-5.1.2\bin\ext\下 重启soapUI 这里连接oracle库获取参数举例说明: 1.在请求里插入一步,选择DataSource 2.选择JDBC 3.点击configure进入配置项 4.输入相关配置然后点击Test connection测试连接成

JDBC的引入及mysql的引入

一.JDBC概念的引入 JDBC是一套接口,实现类是jar包(由提供数据库厂商提供) 完全不关心实现类的内容.只关心接口的方法(也就是只关心JDBC) 二.mysql的引入,绿色包下载 https://www.oracle.com/index.html 下载网址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18-winx64.zip 修改密码的命令:alter user 'root'@'localhost' identified

com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的区别

调试代码时,发现错误: Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary. 在网上巴拉巴拉发现,原

错误:“Cannot load JDBC driver class &#39;com.mysql.jdbc.Driver”的解决方法

"Cannot load JDBC driver class 'com.mysql.jdbc.Driver " 表示没有JDBC连接MySql的驱动包,因此需要手动添加驱动包到WEB-INF目录下的lib目录中. 解决方法: 从网上下载mysql-connector-java.jar,将其放到"D:\workspace\my-web\src\main\webapp\WEB-INF\lib"目录下,即可解决上述问题. 错误:"Cannot load JDBC