7.1 Пул за връзки

Днес ще научим How да работим с базата данни още по-професионално. А сега ще говорим за пула от нишки or пула за връзки на английски.

Свързването с базата данни отнема известно време. Особено ако базата данни е отдалечена. Ако направим връзка с базата данни за всяка заявка, тогава отговорът на нашето приложение ще бъде невероятно бавен като скорост. Да не говорим за ресурсите, които ще консумира.

Като решение на такива проблеми беше предложено връзките към базата да се съхраняват в няHowъв набор, който се нарича пул от нишки.

Когато поискаме нова връзка, пула за връзки я създава и при затваряне не я затваря, а я записва в пула за връзки. И ако отново поискаме връзка от пула за връзки, тя ще ни даде една от старите, instead of да създадем нова.

Всъщност приложението работи чрез специален драйвер, който е обвивка на обикновен JDBC драйвер и който има допълнителна функционалност за работа с пула. Тази ситуация може да бъде представена по следния начин:

пул за свързване

Програмистът може да зададе ръчно настройките за пула на връзките: броя на активните връзки, времето за изчакване и т.н.

За особено екстремни ситуации можете да напишете свой собствен набор от връзки: клас, който ще има списък с връзки. Тя ще замени функцията за затваряне, която ще върне връзката обратно в списъка и ще има много други екстри като таймера за отворена връзка. Когато няма връзка за дълго време, връзката се затваря.

7.2* Интерфейс DataSource и ConnectionPoolDataSource

Пулът от нишки обикновено работи в тандем с обекта DataSource. Този обект може да се разглежда като абстракция на отдалечена база данни. Самото име Data Source буквално може да се преведе като Източник на данни. Което е няHow намек.

DataSource обектите се използват за получаване на физическа връзка към база данни и са алтернатива на DriverManager. Няма нужда да регистрирате JDBC драйвера. Трябва само да зададете подходящите параметри, за да установите връзка иизпълнете метода getConnection()..

Когато създавате обект от типа DataSource локално (директно в приложението), параметрите на връзката се задават чрез подходящите методи, предоставени от доставчика на JDBC драйвер. Тези методи не са дефинирани от интерфейса DataSource, тъй като параметрите за свързване към СУБД от различни доставчици може да се различават Howто по тип, така и по брой (например, не всички СУБД изискват да се посочи типът драйвер or мрежовият протокол).

По този начин, когато работите с СУБД Oracle, за да използвате съответните методи set и get, е необходимо да получите обект от типа OracleDataSource, който е екземпляр на едноименния клас, който имплементира интерфейса DataSource. Следователно този начин на създаване на обекти от типа DataSource прави вашия code по-малко преносим и по-малко зависим от конкретната реализация на драйвера.

Следва пример за code, илюстриращ локалното използване на обекти от тип DataSource.

import java.sql.*;
import javax.sql.*;
import oracle.jdbc.driver.*;
import oracle.jdbc.pool.*;

public class DataSource {
    public static void main(String[] args) {
    	try {
        	OracleDataSource ods = new OracleDataSource();

        	ods.setUser("root");
        	ods.setPassword("secret");
        	ods.setDriverType("thin");
        	ods.setDatabaseName("test");
        	ods.setServerName("localhost");
        	ods.setPortNumber(1521);

        	Connection connection = ods.getConnection();
        	System.out.println("Connection successful!!!");

    	} catch (SQLException se) {
        	se.printStackTrace();
    	}
    	System.out.println("Goodbye!");
	}
}

7.3* JNDI интерфейс

Пълните възможности на обектите от тип DataSource се проявяват в комбинация с използването на JNDI интерфейса. JNDI е специална услуга (нещо като директория) за големи сървърни applications, която позволява на една услуга да установи връзка с друга.

Използването на услугата за име и директория ви позволява да съхранявате обекти от типа DataSource, създадени преди това от системния администратор с предварително зададени параметри на връзката. По-долу са някои от стандартните имена на свойства (параметри), разработени от Sun:

Име на собственост Тип данни на Java Преднаmeaning
име на база данни низ Име на база данни
Име на сървъра низ Име на сървъра
потребител низ Потребителско име (ID)
парола низ Потребителска парола
номер на пристанище вътр Номер на порт на DBMS сървър

Комбинацията от DataSource и JNDI интерфейси играе ключова роля в разработването на многослойни корпоративни applications, базирани на J2EE компонентна технология.

Ако използвате комбинация от интерфейсите DataSource и JNDI в codeа на вашето приложение, трябва само да поискате обект от тип DataSource от услугата за именуване и директория. В този случай подробностите за връзката и програмния code, зависещи от конкретна реализация на драйвера, са скрити от приложението в обекта, съхранен в услугата за име и директория.

По този начин споделянето на обекти от тип DataSource и JNDI включва две стъпки, които се изпълняват независимо една от друга:

  1. Трябва да съхраните именувания обект от тип DataSource в услугата за именуване и директория, като Context.bind()използвате javax.naming.
  2. Поискайте обект от тип DataSource от услугата за именуване и директория в приложението, като използвате Context.lookup(). След това можете да използвате неговия метод, DataSource.getConnection()за да получите връзка с базата данни.

Следното е пример за използване на JNDI интерфейс и обект от тип OracleDataSource заедно.

// Create a key JNDI object
Hashtable env = new Hashtable();
env.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put (Context.PROVIDER_URL, "file:JNDI");
Context ctx = new InitialContext(env);

// Get the DataSource object by its name
DataSource ods = (DataSource) ctx.lookup("myDatabase");

// Get the Connection from the DataSource object
Connection connection = ods.getConnection();
System.out.println("Connection successful!!!");

Няма да анализираме работата на JNDI. Това е извън обхвата на този курс. Просто искам да знаете, че този подход е много често срещан в големи applications. Не се губете, ако видите code като този в бъдеще.

Няма meaning How работи. Просто трябва да знаете, че с JNDI услуга можете да получите прокси обекта на всяка услуга, регистрирана в директорията на услугата. Ето How получавате обекта DataSource и го използвате за работа с базата данни.

7.4 Примери за набор от връзки

Да се ​​върнем там, откъдето започнахме - пулове за свързване.

Java програмистите в своите програми много често използват библиотеки, които съдържат различни реализации на пулове за връзки. Сред тях има три най-популярни:

  • Apache Commons DBCP
  • C3PO
  • HikariCP

Проектът Apache беше първият, който създаде добър набор от връзки, той се използва и в уеб сървъра Tomcat. Пример за работа с него:

public class DBCPDataSource {

    private static BasicDataSource ds = new BasicDataSource();
    static {
    	ds.setUrl("jdbc:h2:mem:test");
    	ds.setUsername("user");
    	ds.setPassword("password");
    	ds.setMinIdle(5);
    	ds.setMaxIdle(10);
    	ds.setMaxOpenPreparedStatements(100);
    }

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

    private DBCPDataSource(){ }
}

Вторият много популярен басейн е C3PO . Странни имена, съгласен съм. Името C3PO е препратка към робота c3po от Star Wars. И също така CP е съкращение от Connection Pool.

public class C3p0DataSource {

    private static ComboPooledDataSource cpds = new ComboPooledDataSource();
    static {
    	try {
        	cpds.setDriverClass("org.h2.Driver");
        	cpds.setJdbcUrl("jdbc:h2:mem:test");
        	cpds.setUser("user");
        	cpds.setPassword("password");
    	} catch (PropertyVetoException e) {
            // handle the exception
    	}
    }

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

    private C3p0DataSource(){}
}

Документация за него можете да намерите на официалната page .

И накрая, най-популярният Connection Pool в наше време е HikariCP :

public class HikariCPDataSource {

    private static HikariConfig config = new HikariConfig();
    private static HikariDataSource ds;

    static {
    	config.setJdbcUrl("jdbc:h2:mem:test");
    	config.setUsername("user");
    	config.setPassword("password");
    	config.addDataSourceProperty("cachePrepStmts", "true");
    	config.addDataSourceProperty("prepStmtCacheSize", "250");
    	config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
    	ds = new HikariDataSource(config);
    }

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

    private HikariCPDataSource(){}
}

Ето неговата официална page в GitHub .

И добра статия за конфигурацията.