7.1 Tilkoblingsbasseng

I dag skal vi lære å jobbe enda mer profesjonelt med databasen. Og nå skal vi snakke om trådpoolen, eller forbindelsespoolen på engelsk.

Det tar litt tid å koble til databasen. Spesielt hvis databasen er ekstern. Hvis vi oppretter en tilkobling til databasen for hver forespørsel, vil svaret til applikasjonen vår være utrolig treg i hastighet. For ikke å snakke om ressursene det vil forbruke.

Som en løsning på slike problemer ble det foreslått å lagre forbindelser til basen i et sett, som kalles trådbassenget.

Når vi ber om en ny tilkobling oppretter tilkoblingspoolen den, og når den lukkes lukker den den ikke, men lagrer den i tilkoblingspoolen. Og hvis vi ber om en tilkobling fra tilkoblingspoolen igjen, vil det gi oss en av de gamle i stedet for å opprette en ny.

Faktisk fungerer applikasjonen gjennom en spesiell driver, som er en innpakning for en vanlig JDBC-driver og som har tilleggsfunksjonalitet for å jobbe med bassenget. Denne situasjonen kan representeres som følger:

tilkoblingsbasseng

Programmereren kan stille inn innstillingene for tilkoblingspoolen manuelt: antall aktive tilkoblinger, tidsavbrudd osv.

For spesielt ekstreme situasjoner kan du skrive din egen tilkoblingspool: en klasse som vil ha en liste over tilkoblinger. Den vil overstyre lukkefunksjonen, som vil returnere tilkoblingen tilbake til listen, og det vil være mange andre godbiter som timeren for åpen tilkobling. Når det ikke er noen forbindelse på lang tid, er forbindelsen stengt.

7.2* Interface DataSource og ConnectionPoolDataSource

Trådpoolen fungerer vanligvis sammen med DataSource-objektet. Dette objektet kan betraktes som en abstraksjon av en ekstern database. Selve navnet Datakilde kan bokstavelig talt oversettes som Datakilde. Noe som er et slags hint.

DataSource-objekter brukes til å få en fysisk tilkobling til en database og er et alternativ til DriverManager. Det er ikke nødvendig å registrere JDBC-driveren. Du trenger bare å stille inn de riktige parameterne for å opprette en tilkobling ogutfør getConnection()-metoden.

Når du oppretter et objekt av DataSource-typen lokalt (direkte i applikasjonen), angis tilkoblingsparameterne med de riktige metodene som tilbys av JDBC-driverleverandøren. Disse metodene er ikke definert av DataSource-grensesnittet, siden parametrene for tilkobling til DBMS fra forskjellige leverandører kan variere både i type og antall (for eksempel krever ikke alle DBMS at typen driver eller nettverksprotokoll spesifiseres).

Når du arbeider med Oracle DBMS, for å bruke det tilsvarende settet og hentemetodene, er det derfor nødvendig å skaffe et objekt av typen OracleDataSource, som er en forekomst av klassen med samme navn som implementerer DataSource-grensesnittet. Derfor gjør denne måten å lage objekter av typen DataSource på koden din mindre portabel og mindre avhengig av den spesifikke implementeringen av driveren.

Følgende er et kodeeksempel som illustrerer lokal bruk av objekter av typen 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-grensesnitt

De fulle egenskapene til objekter av typen DataSource manifesteres i kombinasjon med bruken av JNDI-grensesnittet. JNDI er en spesiell tjeneste (noe sånt som en katalog) for store serverapplikasjoner som lar en tjeneste etablere en forbindelse med en annen.

Ved å bruke navnet og katalogtjenesten kan du lagre objekter av typen DataSource som tidligere er opprettet av systemadministratoren med forhåndsdefinerte tilkoblingsparametere. Følgende er noen av standardegenskapsnavnene (parameternavnene) utviklet av Sun:

Eiendomsnavn Java-datatype Hensikt
databasenavn String Databasenavn
Server navn String Server navn
bruker String Brukernavn (ID)
passord String Bruker passord
portnummer int DBMS-serverportnummer

Kombinasjonen av DataSource- og JNDI-grensesnitt spiller en nøkkelrolle i utviklingen av multi-tier enterprise-applikasjoner basert på J2EE-komponentteknologi.

Hvis du bruker en kombinasjon av DataSource- og JNDI-grensesnittene i applikasjonskoden din, trenger du bare å be om et objekt av typen DataSource fra navne- og katalogtjenesten. I dette tilfellet er detaljene for tilkoblingen og programkoden avhengig av en bestemt implementering av driveren skjult fra applikasjonen i objektet som er lagret i navn og katalogtjeneste.

Dermed involverer deling av objekter av typen DataSource og JNDI to trinn som utføres uavhengig av hverandre:

  1. Du må lagre det navngitte objektet av typen DataSource i navne- og katalogtjenesten ved å Context.bind()bruke javax.naming.
  2. Be om et objekt av typen DataSource fra navne- og katalogtjenesten i applikasjonen ved å bruke Context.lookup(). Etter det kan du bruke metoden DataSource.getConnection()for å få en tilkobling til databasen.

Følgende er et eksempel på bruk av JNDI-grensesnittet og et objekt av typen OracleDataSource sammen.

// 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!!!");

Vi vil ikke analysere arbeidet til JNDI. Dette er utenfor rammen av dette kurset. Jeg vil bare at du skal vite at denne tilnærmingen er veldig vanlig i store applikasjoner. Ikke gå deg vill hvis du ser kode som dette i fremtiden.

Det spiller ingen rolle hvordan det fungerer. Du trenger bare å vite at med en JNDI-tjeneste kan du få proxy-objektet til enhver tjeneste som er registrert i tjenestekatalogen. Slik får du DataSource-objektet og bruker det til å jobbe med databasen.

7.4 Eksempler på tilkoblingsbasseng

La oss komme tilbake til der vi startet - tilkoblingsbassenger.

Java-programmerere i programmene deres bruker veldig ofte biblioteker som inneholder ulike implementeringer av tilkoblingspooler. Blant dem er det tre mest populære:

  • Apache Commons DBCP
  • C3PO
  • HikariCP

Apache-prosjektet var det første som skapte et godt tilkoblingsbasseng, det brukes også inne i Tomcat-nettserveren. Et eksempel på å jobbe med det:

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(){ }
}

Det andre veldig populære bassenget er C3PO . Merkelige navn, jeg er enig. Navnet C3PO er en referanse til c3po-roboten fra Star Wars. Og også CP er forkortelse for 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(){}
}

Dokumentasjon for det finnes på den offisielle siden .

Og til slutt, den mest populære Connection Pool i vår tid er 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(){}
}

Her er hans offisielle GitHub- side .

Og en god artikkel om konfigurasjon.