Источник данных Java, пример источника данных JDBC
Источник данных Java
В большинстве случаев мы ищем слабую связь для подключения, чтобы мы могли легко переключаться между базами данных, пулом соединений для управления транзакциями и поддержкой распределенных систем. JDBC DataSource является предпочтительным подходом, если вы ищете какие-либо из этих функций в своем приложении. Интерфейс Java DataSource присутствует в пакете javax.sql
и объявляет только два перегруженных метода getConnection()
и getConnection(String str1,String str2)
.
Источник данных JDBC
Различные поставщики баз данных несут ответственность за предоставление различных видов реализации интерфейса DataSource. Например, драйвер MySQL JDBC обеспечивает базовую реализацию интерфейса DataSource с классом com.mysql.jdbc.jdbc2.Optional.MysqlDataSource
, а драйвер базы данных Oracle реализует его с помощью oracle.jdbc.pool.OracleDataSource
класс. Эти классы реализации предоставляют методы, с помощью которых мы можем предоставить сведения о сервере базы данных с учетными данными пользователя. Вот некоторые из других общих функций, предоставляемых этими классами реализации JDBC DataSource;
- Кэширование PreparedStatement для более быстрой обработки
- Настройки времени ожидания подключения
- Функции ведения журнала
- Порог максимального размера ResultSet
Пример источника данных JDBC
Java JDBC DataSource — настройка базы данных
Прежде чем мы перейдем к нашим примерам программ, нам нужно настроить базу данных с таблицами и примерами данных. Установка базы данных MySQL или Oracle выходит за рамки этого руководства, поэтому я просто настрою таблицу с примерами данных.
--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;
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;
Теперь давайте перейдем к нашим java-программам. Поскольку конфигурация базы данных слабо связана, я буду читать их из файла свойств. файл 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
Убедитесь, что приведенные выше конфигурации соответствуют вашим локальным настройкам. Также убедитесь, что в путь сборки проекта включены jar-файлы MySQL и Oracle DB JDBC.
Java JDBC DataSource — пример MySQL, Oracle
Давайте напишем фабричный класс, который мы можем использовать для получения MySQL или Oracle DataSource.
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;
}
}
Обратите внимание, что классы реализации Oracle и MySQL DataSource очень похожи, давайте напишем простую тестовую программу для использования этих методов и проведем некоторый тест.
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();
}
}
}
}
Обратите внимание, что клиентский класс полностью независим от каких-либо конкретных классов базы данных. Это помогает нам скрыть основные детали реализации от клиентской программы и получить преимущества слабой связи и абстракции. Когда мы запустим вышеуказанную тестовую программу, мы получим вывод ниже.
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
Если вы посмотрите на фабричный класс Java DataSource выше, то увидите, что с ним связаны две основные проблемы.
- Методы фабричного класса для создания MySQL и Oracle DataSource тесно связаны с соответствующим API-интерфейсом драйвера. Если в будущем мы захотим отказаться от поддержки базы данных Oracle или добавить поддержку какой-либо другой базы данных, это потребует изменения кода.
- Большая часть кода для получения MySQL и Oracle DataSource похожа, единственное различие заключается в используемом нами классе реализации.
Apache Commons DBCP API помогает нам избавиться от этих проблем, предоставляя реализацию Java DataSource, которая работает как уровень абстракции между нашей программой и различными драйверами JDBC. Библиотека Apache DBCP зависит от библиотеки Commons Pool, поэтому убедитесь, что обе они находятся в пути сборки, как показано на рисунке. Вот класс фабрики DataSource, использующий BasicDataSource, который является простой реализацией DataSource.
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;
}
}
Как видите, в зависимости от ввода пользователя создается либо MySQL, либо Oracle DataSource. Если вы поддерживаете только одну базу данных в приложении, вам даже не нужна эта логика. Просто измените свойства, и вы сможете переключаться с одного сервера базы данных на другой. Ключевым моментом, с помощью которого Apache DBCP обеспечивает абстракцию, является метод setDriverClassName(). Вот клиентская программа, использующая вышеуказанный фабричный метод для получения различных типов соединения.
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();
}
}
}
}
Когда вы запустите вышеуказанную программу, вывод будет таким же, как и в предыдущей программе. Если вы посмотрите на использование Java JDBC DataSource и выше, это можно сделать и с обычным DriverManager. Основное преимущество Java DataSource заключается в том, что он используется в контексте и с JNDI. С помощью простых конфигураций мы можем создать пул соединений с базой данных, который будет поддерживаться самим контейнером. Большинство контейнеров сервлетов, таких как Tomcat и JBoss, предоставляют собственную реализацию Java DataSource, и все, что нам нужно, — это настроить его с помощью простых конфигураций на основе XML, а затем использовать поиск контекста JNDI для получения Java DataSource и работы с ним. Это помогает нам заботиться о пуле соединений и управлении ими со стороны нашего приложения на стороне сервера и, таким образом, дает нам больше времени для написания бизнес-логики для приложения. В следующем руководстве мы узнаем, как настроить источник данных в контейнере Tomcat и использовать его в веб-приложении.