PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Erstellen Sie programmgesteuert ein `DataSource`-Objekt für Postgres JDBC

tl;dr

Die PGSimpleDataSource -Klasse, die mit dem JDBC-Treiber von jdbc.postgresql.org gebündelt ist, implementiert DataSource Schnittstelle. Konfigurieren Sie Ihre Datenbankverbindungsdetails in einer PGSimpleDataSource -Objekt und als DataSource herumreichen Objekt.

PGSimpleDataSource ds = new PGSimpleDataSource() ;  
ds.setServerName( "localhost" );  
ds.setDatabaseName( "your_db_name_here" );   
ds.setUser( "scott" );       
ds.setPassword( "tiger" );   

Verwenden Sie dieses Objekt, um bei Bedarf eine Verbindung zur Datenbank herzustellen. Verwenden Sie die praktische Try-with-Ressourcen-Syntax.

try
(
    Connection conn = ds.getConnection() ;
) 
{ … }

Implementierung des JDBC-Treibers

Ihr JDBC-Treiber kann Ihnen eine Implementierung der DataSource bereitstellen Schnittstelle.

Ein Objekt dieser Implementierung enthält die Informationen, die benötigt werden, um eine Verbindung zur Datenbank herzustellen und zu konfigurieren, wie zum Beispiel:

  • Name und Passwort des Datenbankbenutzers
  • IP-Adresse und Portnummer des Datenbankservers

Es können bis zu drei Arten von bereitgestellter Implementierung verfügbar sein:

  • Oft ist eine solche Implementierung ein dünner Wrapper um den DriverManager . Jedes Mal, wenn Sie DataSource::getConnection aufrufen Aufgrund einer solchen Implementierung erhalten Sie eine neue Datenbankverbindung.
  • Alternativ kann eine Implementierung einen Verbindungspool darunter verwenden, um bereits vorhandene Verbindungen bereitzustellen. Diese Verbindungen werden ausgehändigt und wieder eingecheckt, wie Bücher in einer Bibliothek, um für den wiederholten Gebrauch recycelt zu werden.
  • Eine Implementierung kann die Java-Transaktions-API unterstützen, die X/Open XA unterstützt, für anspruchsvolle Anforderungen wie die Koordination der Transaktionen über mehrere Ressourcen wie Datenbanken und Nachrichtenwarteschlangen hinweg. Nicht so häufig verwendet, daher ignoriere ich diesen Typ hier.

Treiber von jdbc.postgresql.org

Der kostenlose Open-Source-Treiber von jdbc.postgresql.org bietet alle drei Arten von DataSource Implementierung. Die Autoren empfehlen jedoch nicht, ihren Verbindungspooltyp tatsächlich in der Produktion zu verwenden. Wenn Sie Pooling wünschen, verwenden Sie eine Verbindungspooling-Bibliothek eines Drittanbieters. Und wir ignorieren den Typ XA.

Schauen wir uns also die einfache Implementierung von DataSource an, bei der jede Verbindung neu hergestellt wird :org.postgresql.ds.PGSimpleDataSource

Konfigurieren des Datenquellenobjekts

Instanziieren Sie ein leeres Objekt und rufen Sie dann eine Reihe von Setter-Methoden auf, um es für Ihr spezielles Datenbankszenario zu konfigurieren. Die Setter-Methoden werden von org.postgresql.ds.common.BaseDataSource geerbt .

Wir führen noch kein Upcasting zur Schnittstelle DataSource durch , damit wir die verschiedenen Setter-Methoden aufrufen können. Siehe Beispielcode und Diskussion auf der Seite Datenquellen und JNDI.

PGSimpleDataSource ds = new PGSimpleDataSource() ;  // Empty instance.
ds.setServerName( "localhost" );  // The value `localhost` means the Postgres cluster running locally on the same machine.
ds.setDatabaseName( "testdb" );   // A connection to Postgres must be made to a specific database rather than to the server as a whole. You likely have an initial database created named `public`.
ds.setUser( "testuser" );         // Or use the super-user 'postgres' for user name if you installed Postgres with defaults and have not yet created user(s) for your application.
ds.setPassword( "password" );     // You would not really use 'password' as a password, would you?

Im Allgemeinen würde ich diese separaten Setter-Methoden verwenden. Alternativ konstruieren Sie einen String, eine URL, mit den verschiedenen Informationen, die auf der DataSource festgelegt werden sollen in einem Schlag. Wenn Sie diesen Weg gehen möchten, rufen Sie setUrl auf .

Damit sind die Grundlagen abgedeckt. Aber vielleicht möchten oder brauchen Sie einige der anderen Setter. Die meisten davon setzen Postgres-Eigenschaftswerte auf dem Server. Die Eigenschaften haben alle intelligente Standardwerte, aber Sie können sie in besonderen Situationen überschreiben.

ds.setPortNumber( 6787 ) ;  // If not using the default '5432'.
ds.setApplicationName( "whatever" ) ;   // Identify the application making this connection to the database. Also a clever way to back-door some information to the Postgres server, as you can encode small values into this string for later parsing. 
ds.setConnectTimeout( … ) ;  // The timeout value used for socket connect operations, in whole seconds. If connecting to the server takes longer than this value, the connection is broken.
ds.setSocketTimeout( … ) ;  // The timeout value used for socket read operations. If reading from the server takes longer than this value, the connection is closed. This can be used as both a brute force global query timeout and a method of detecting network problems.
ds.setReadOnly( boolean ) ;  // Puts this connection in read-only mode.

Wenn Sie TLS (früher bekannt als SSL) verwenden, um die Datenbankverbindung zu verschlüsseln, um sie vor Abhören oder böswilliger Manipulation zu schützen, verwenden Sie dafür mehrere Setter.

Für jede Postgres-Eigenschaft ohne eine bestimmte Setter-Methode können Sie setProperty( PGProperty property, String value ) aufrufen .

Sie können die Einstellungen dieser Datenquelle überprüfen oder überprüfen, indem Sie eine der vielen Getter-Methoden aufrufen.

Nach der Konfiguration Ihrer PGSimpleDataSource , können Sie einfach als DataSource an den Rest Ihrer Codebasis übergeben Objekt. Dies schützt Ihre Codebasis vor dem Schock des Wechsels zu einer anderen DataSource Implementierung oder Wechsel zu einem anderen JDBC-Treiber.

DataSource dataSource = ds ;  // Upcasting from concrete class to interface.
return dataSource ; 

Verwendung der Datenquelle

Verwenden einer DataSource ist absolut einfach, da es nur zwei Methoden bereitstellt, ein Paar Variationen von getConnection um eine Connection herzustellen Objekt für Ihre Datenbankarbeit.

Connection conn = dataSource.getConnection() ; 

Wenn Sie mit Ihrer Connection fertig sind , ist es am besten, es zu schließen. Verwenden Sie entweder eine try-with-resources-Syntax, um die Verbindung automatisch zu schließen, oder schließen Sie sie explizit.

conn.close() ;

Denken Sie daran, dass eine DataSource ist nicht wirklich eine Datenquelle. Eine DataSource ist wirklich eine Quelle zum Generieren/Zugreifen auf Verbindungen zur Datenbank. Meiner Meinung nach ist dies eine falsche Bezeichnung, da ich es als ConnectionSource betrachte . Die DataSource spricht nur lange genug mit Ihrer Datenbank, um sich mit Benutzername und Passwort anzumelden. Nach dieser Anmeldung verwenden Sie die Connection Objekt, um mit der Datenbank zu interagieren.

Speichern Ihrer DataSource

Nach der Konfiguration möchten Sie diese DataSource beibehalten Objekt herum, zwischengespeichert. Keine Notwendigkeit, wiederholt neu zu konfigurieren. Die Implementierung sollte Thread-sicher geschrieben werden. Sie können getConnection aufrufen jederzeit und überall.

Für eine einfache kleine Java-App möchten Sie sie vielleicht als Feld in einem Singleton oder in einer statischen globalen Variablen speichern.

Für eine Servlet-basierte Anwendung wie Vaadin app erstellen Sie eine Klasse, die ServletContextListener implementiert Schnittstelle. In dieser Klasse würden Sie Ihre DataSource einrichten -Objekt, wenn Ihre Web-App gestartet wird. Von dort würden Sie das Objekt im ServletContext speichern Objekt durch Übergabe an setAttribute . Context ist der Fachbegriff für „Web-App“. Abrufen durch Aufrufen von getAttribute und Casting in DataSource .

In einem Unternehmensszenario ist die DataSource kann in einer JNDI-kompatiblen Implementierung gespeichert werden. Einige Servlet-Container wie Apache Tomcat bieten möglicherweise eine JNDI-Implementierung. Einige Organisationen verwenden einen Server wie einen LDAP-Server. Registrieren und Abrufen Ihrer DataSource Objekt mit JNDI wird in vielen anderen Fragen und Antworten zu Stack Overflow behandelt.