7.1 Anslutningspool

Idag ska vi lära oss hur man arbetar med databasen ännu mer professionellt. Och nu ska vi prata om trådpoolen, eller anslutningspoolen på engelska.

Att ansluta till databasen tar lite tid. Speciellt om databasen är avlägsen. Om vi ​​gör en anslutning till databasen för varje begäran kommer svaret från vår applikation att vara otroligt långsam i hastighet. För att inte tala om resurserna det kommer att förbruka.

Som en lösning på sådana problem föreslogs det att lagra anslutningar till basen i någon uppsättning, som kallas trådpoolen.

När vi begär en ny anslutning skapar anslutningspoolen den, och när den är stängd stänger den den inte utan sparar den i anslutningspoolen. Och om vi begär en anslutning från anslutningspoolen igen, kommer det att ge oss en av de gamla istället för att skapa en ny.

Faktum är att applikationen fungerar genom en speciell drivrutin, som är ett omslag för en vanlig JDBC-drivrutin och som har ytterligare funktionalitet för att arbeta med poolen. Denna situation kan representeras enligt följande:

anslutning pool

Programmeraren kan ställa in inställningarna för anslutningspoolen manuellt: antalet aktiva anslutningar, timeout, etc.

För särskilt extrema situationer kan du skriva din egen anslutningspool: en klass som kommer att ha en lista med anslutningar. Det kommer att åsidosätta stängningsfunktionen, som kommer att återföra anslutningen till listan, och det kommer att finnas många andra godsaker som timern för öppen anslutning. När det inte finns någon anslutning under en längre tid stängs anslutningen.

7.2* Interface DataSource och ConnectionPoolDataSource

Trådpoolen fungerar vanligtvis tillsammans med DataSource-objektet. Detta objekt kan ses som en abstraktion av en fjärrdatabas. Själva namnet Datakälla kan bokstavligen översättas som Datakälla. Vilket är en antydan.

DataSource-objekt används för att få en fysisk anslutning till en databas och är ett alternativ till DriverManager. Det finns inget behov av att registrera JDBC-drivrutinen. Du behöver bara ställa in lämpliga parametrar för att upprätta en anslutning ochkör metoden getConnection()..

När du skapar ett objekt av typen DataSource lokalt (direkt i applikationen), ställs anslutningsparametrarna in med lämpliga metoder som tillhandahålls av JDBC-drivrutinsleverantören. Dessa metoder definieras inte av DataSource-gränssnittet, eftersom parametrarna för att ansluta till DBMS från olika leverantörer kan skilja sig åt både i typ och antal (till exempel kräver inte alla DBMS att typen av drivrutin eller nätverksprotokoll anges).

När man arbetar med Oracle DBMS, för att använda motsvarande set och få metoder, är det därför nödvändigt att erhålla ett objekt av typen OracleDataSource, som är en instans av klassen med samma namn som implementerar DataSource-gränssnittet. Därför gör detta sätt att skapa objekt av typen DataSource din kod mindre portabel och mindre beroende av den specifika implementeringen av drivrutinen.

Följande är ett kodexempel som illustrerar den lokala användningen av objekt 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-gränssnitt

De fulla funktionerna hos objekt av typen DataSource manifesteras i kombination med användningen av JNDI-gränssnittet. JNDI är en speciell tjänst (något liknande en katalog) för stora serverapplikationer som gör att en tjänst kan upprätta en anslutning till en annan.

Genom att använda namn- och katalogtjänsten kan du lagra objekt av typen DataSource som tidigare skapats av systemadministratören med fördefinierade anslutningsparametrar. Följande är några av standardegenskapsnamnen (parameternamn) som utvecklats av Sun:

Egendomsnamn Java-datatyp Syfte
Databas namn Sträng Databas namn
server namn Sträng Server namn
användare Sträng Användarnamn (ID)
Lösenord Sträng Användarlösenord
portnummer int DBMS-serverportnummer

Kombinationen av DataSource- och JNDI-gränssnitt spelar en nyckelroll i utvecklingen av multi-tier företagsapplikationer baserade på J2EE-komponentteknologi.

Om du använder en kombination av DataSource- och JNDI-gränssnitten i din applikationskod behöver du bara begära ett objekt av typen DataSource från namn- och katalogtjänsten. I det här fallet döljs detaljerna för anslutningen och programkoden beroende på en viss implementering av drivrutinen från applikationen i objektet som är lagrat i namn- och katalogtjänsten.

Således innebär delning av objekt av typen DataSource och JNDI två steg som utförs oberoende av varandra:

  1. Du måste lagra det namngivna objektet av typen DataSource i namn- och katalogtjänsten med hjälp Context.bind()av javax.naming.
  2. Begär ett objekt av typen DataSource från namn- och katalogtjänsten i applikationen med hjälp av Context.lookup(). Efter det kan du använda dess metod DataSource.getConnection()för att få en anslutning till databasen.

Följande är ett exempel på hur JNDI-gränssnittet och ett objekt av typen OracleDataSource används tillsammans.

// 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 kommer inte att analysera JNDI:s arbete. Detta ligger utanför ramen för denna kurs. Jag vill bara att du ska veta att detta tillvägagångssätt är mycket vanligt i stora applikationer. Gå inte vilse om du ser kod som denna i framtiden.

Det spelar ingen roll hur det fungerar. Du behöver bara veta att med en JNDI-tjänst kan du få proxyobjektet för vilken tjänst som helst som är registrerad i tjänstekatalogen. Så här hämtar du DataSource-objektet och använder det för att arbeta med databasen.

7.4 Exempel på anslutningspool

Låt oss gå tillbaka till där vi började - anslutningspooler.

Java-programmerare i sina program använder väldigt ofta bibliotek som innehåller olika implementeringar av anslutningspooler. Bland dem finns tre mest populära:

  • Apache Commons DBCP
  • C3PO
  • HikariCP

Apache-projektet var det första som skapade en bra anslutningspool, den används även inuti Tomcat-webbservern. Ett exempel på att arbeta 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(){ }
}

Den andra mycket populära poolen är C3PO . Konstiga namn, jag håller med. Namnet C3PO är en referens till c3po-roboten från Star Wars. Och även CP är en förkortning för 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(){}
}

Dokumentation för det finns på den officiella sidan .

Och slutligen, den mest populära anslutningspoolen i vår tid är 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(){}
}

Här är hans officiella GitHub- sida .

Och en bra artikel om konfiguration.