PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Produire un objet `DataSource` pour Postgres JDBC, par programme

tl;dr

Le PGSimpleDataSource la classe fournie avec le pilote JDBC de jdbc.postgresql.org implémente DataSource interface. Configurez vos détails de connexion à la base de données dans un PGSimpleDataSource objet et le transmettre en tant que DataSource objet.

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

Utilisez cet objet pour établir une connexion à la base de données si nécessaire. Utilisez une syntaxe d'essai pratique avec des ressources.

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

Implémentation du pilote JDBC

Votre pilote JDBC peut vous fournir une implémentation du DataSource interface.

Un objet de cette implémentation contient les informations nécessaires pour établir et configurer une connexion à la base de données, telles que :

  • Nom et mot de passe de l'utilisateur de la base de données
  • Adresse IP et numéro de port du serveur de base de données

Jusqu'à trois types d'implémentation peuvent être disponibles :

  • Souvent, une telle implémentation est une mince enveloppe autour du DriverManager . Chaque fois que vous appelez DataSource::getConnection sur l'objet d'une telle implémentation, vous obtenez une nouvelle connexion à la base de données.
  • Alternativement, une mise en œuvre peut utiliser un pool de connexions en dessous pour fournir des connexions déjà existantes. Ces connexions sont distribuées et réintégrées, comme des livres dans une bibliothèque, pour être recyclées en vue d'une utilisation répétée.
  • Une implémentation peut prendre en charge l'API Java Transaction, prenant en charge X/Open XA, pour des besoins sophistiqués tels que la coordination des transactions sur plusieurs ressources telles que des bases de données et des files d'attente de messages. Pas aussi couramment utilisé, j'ignore donc ce type ici.

Pilote de jdbc.postgresql.org

Le pilote open source gratuit de jdbc.postgresql.org fournit les trois types de DataSource la mise en oeuvre. Mais les auteurs ne recommandent pas d'utiliser réellement leur type de pool de connexion en production; si vous souhaitez un regroupement, utilisez une bibliothèque de regroupement de connexions tierce. Et nous ignorons le type XA.

Regardons donc l'implémentation simple de DataSource avec une nouvelle connexion à chaque fois :org.postgresql.ds.PGSimpleDataSource

Configuration de l'objet source de données

Instanciez un objet vide, puis appelez une série de méthodes setter à configurer pour votre scénario de base de données particulier. Les méthodes setter sont héritées de org.postgresql.ds.common.BaseDataSource .

Nous ne procédons pas encore à la conversion vers l'interface DataSource , afin que nous puissions appeler les différentes méthodes de définition. Voir l'exemple de code et la discussion sur la page Sources de données et 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?

Généralement, j'utiliserais ces méthodes de setter séparées. Alternativement, vous construisez une chaîne, une URL, avec les différentes informations à définir sur le DataSource d'un seul coup. Si vous voulez emprunter cette voie, appelez setUrl .

Cela couvre les bases. Mais vous pourriez vouloir ou avoir besoin de certains des autres passeurs. La plupart d'entre eux définissent les valeurs des propriétés Postgres sur le serveur. Les propriétés ont toutes des valeurs par défaut intelligentes, mais vous souhaiterez peut-être les remplacer dans des situations particulières.

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.

Si vous utilisez TLS (anciennement connu sous le nom de SSL) pour chiffrer la connexion à la base de données afin de vous protéger contre les écoutes clandestines ou les manipulations malveillantes, utilisez plusieurs setters pour cela.

Pour toute propriété Postgres sans méthode setter spécifique, vous pouvez appeler setProperty( PGProperty property, String value ) .

Vous pouvez inspecter ou vérifier les paramètres de cette source de données en appelant l'une des nombreuses méthodes getter.

Après avoir configuré votre PGSimpleDataSource , vous pouvez passer au reste de votre base de code comme un simple DataSource objet. Cela isole votre base de code du choc du passage à un autre DataSource l'implémentation ou le passage à un autre pilote JDBC.

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

Utilisation de la source de données

Utiliser un DataSource est tout à fait simple car il ne fournit que deux méthodes, une paire de variations sur getConnection pour obtenir une Connection objet pour votre travail de base de données.

Connection conn = dataSource.getConnection() ; 

Lorsque vous avez terminé avec votre Connection , la meilleure pratique consiste à s'assurer de le fermer. Utilisez une syntaxe try-with-resources pour fermer automatiquement la connexion, ou fermez-la explicitement.

conn.close() ;

Gardez bien à l'esprit qu'un DataSource n'est pas réellement une source de données. Un DataSource est vraiment une source pour générer/accéder aux connexions à la base de données. À mon avis, c'est un terme impropre, car je le considère comme ConnectionSource . Le DataSource ne parle à votre base de données que le temps nécessaire pour se connecter avec un nom d'utilisateur et un mot de passe. Après cette connexion, vous utilisez la Connection objet pour interagir avec la base de données.

Stocker votre DataSource

Une fois configuré, vous souhaitez conserver ce DataSource objet autour, mis en cache. Pas besoin de reconfigurer à plusieurs reprises. L'implémentation doit être écrite pour être thread-safe. Vous pouvez appeler getConnection à tout moment de n'importe où.

Pour une petite application Java simple, vous souhaiterez peut-être la stocker sous forme de champ sur un singleton ou dans une variable globale statique.

Pour une application basée sur Servlet telle qu'un Vaadin app, vous créeriez une classe implémentant ServletContextListener interface. Dans cette classe, vous établiriez votre DataSource objet lors du lancement de votre application Web. De là, vous stockeriez l'objet dans le ServletContext objet en passant à setAttribute . Context est le terme technique pour 'application web'. Récupérez en appelant getAttribute et transtypage vers DataSource .

Dans un scénario d'entreprise, le DataSource peuvent être stockés dans une implémentation compatible JNDI. Certains conteneurs de servlet tels qu'Apache Tomcat peuvent fournir une implémentation JNDI. Certaines organisations utilisent un serveur tel qu'un serveur LDAP. Enregistrement et récupération de votre DataSource objet avec JNDI est couvert dans de nombreuses autres questions et réponses sur Stack Overflow.