PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Produci un oggetto `DataSource` per Postgres JDBC, a livello di codice

tl;dr

Il PGSimpleDataSource la classe in bundle con il driver JDBC da jdbc.postgresql.org implementa DataSource interfaccia. Configura i dettagli della connessione al database in un PGSimpleDataSource oggetto e passare come DataSource oggetto.

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

Utilizzare quell'oggetto per stabilire una connessione al database secondo necessità. Usa la comoda sintassi Prova con le risorse.

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

Implementazione del driver JDBC

Il tuo driver JDBC potrebbe fornirti un'implementazione del DataSource interfaccia.

Un oggetto di questa implementazione contiene le informazioni necessarie per effettuare e configurare una connessione al database, come ad esempio:

  • Nome e password dell'utente del database
  • Indirizzo IP e numero di porta del server di database

Possono essere disponibili fino a tre tipi di implementazione forniti:

  • Spesso una tale implementazione è un sottile involucro attorno al DriverManager . Ogni volta che chiami DataSource::getConnection sull'oggetto di tale implementazione, ottieni una nuova connessione al database.
  • In alternativa, un'implementazione potrebbe utilizzare un pool di connessioni sottostante per fornire connessioni già esistenti. Queste connessioni vengono distribuite e archiviate, come i libri in una biblioteca, per essere riciclate per un uso ripetuto.
  • Un'implementazione può supportare Java Transaction API, supportando X/Open XA, per esigenze sofisticate come il coordinamento delle transazioni su più risorse come database e code di messaggi. Non è comunemente usato, quindi ignoro questo tipo qui.

Driver da jdbc.postgresql.org

Il driver gratuito open source di jdbc.postgresql.org fornisce tutti e tre i tipi di DataSource implementazione. Ma gli autori sconsigliano di utilizzare effettivamente il loro tipo di pool di connessioni in produzione; se si desidera il pool, utilizzare una libreria di pool di connessioni di terze parti. E stiamo ignorando il tipo XA.

Diamo quindi un'occhiata alla semplice implementazione della nuova connessione ogni volta di DataSource :org.postgresql.ds.PGSimpleDataSource

Configurazione dell'oggetto origine dati

Crea un'istanza di un oggetto vuoto, quindi chiama una serie di metodi setter da configurare per il tuo particolare scenario di database. I metodi setter sono ereditati da org.postgresql.ds.common.BaseDataSource .

Non stiamo ancora eseguendo l'upcast all'interfaccia DataSource , in modo da poter chiamare i vari metodi setter. Vedi codice di esempio e discussione nella pagina Fonti dati e 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?

Generalmente userei questi metodi di setter separati. In alternativa, costruisci una String, un URL, con le varie informazioni da impostare sul DataSource in un colpo. Se vuoi seguire quella strada, chiama setUrl .

Questo copre le basi. Ma potresti voler o aver bisogno di alcuni degli altri setter. La maggior parte di questi impostano i valori delle proprietà Postgres sul server. Le proprietà hanno tutte impostazioni predefinite intelligenti, ma potresti voler sovrascrivere per situazioni speciali.

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.

Se si utilizza TLS (precedentemente noto come SSL) per crittografare la connessione al database per proteggersi da intercettazioni o manipolazioni malevole, utilizzare diversi setter per questo.

Per qualsiasi proprietà Postgres senza un metodo setter specifico, puoi chiamare setProperty( PGProperty property, String value ) .

Puoi controllare o verificare le impostazioni su questa origine dati chiamando uno dei tanti metodi getter.

Dopo aver configurato il tuo PGSimpleDataSource , puoi passare al resto della tua base di codice semplicemente come un DataSource oggetto. Questo isola la tua base di codice dallo shock di passare a un altro DataSource implementazione o passaggio a un altro driver JDBC.

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

Utilizzo dell'origine dati

Utilizzando un DataSource è assolutamente semplice in quanto fornisce solo due metodi, un paio di variazioni su getConnection per ottenere una Connection oggetto per il tuo lavoro nel database.

Connection conn = dataSource.getConnection() ; 

Al termine della tua Connection , la migliore pratica è assicurarsi di chiuderlo. Utilizza una sintassi Prova con le risorse per chiudere automaticamente la connessione o chiuderla in modo esplicito.

conn.close() ;

Tieni a mente che un DataSource non è in realtà una fonte di dati. Un DataSource è davvero una fonte per generare/accedere alle connessioni al database. A mio avviso, questo è un termine improprio, poiché lo considero ConnectionSource . Il DataSource comunica con il tuo database solo il tempo necessario per accedere con nome utente e password. Dopo aver effettuato l'accesso, utilizzerai la Connection oggetto per interagire con il database.

Memorizzare il tuo DataSource

Una volta configurato, vuoi mantenere quel DataSource oggetto in giro, memorizzato nella cache. Non è necessario riconfigurare ripetutamente. L'implementazione deve essere scritta per essere thread-safe. Puoi chiamare getConnection in qualsiasi momento da qualsiasi luogo.

Per una semplice piccola app Java, potresti volerla archiviare come campo su un singleton o in una variabile globale statica.

Per un'app basata su servlet come un Vaadin app, creeresti una classe che implementa ServletContextListener interfaccia. In quella classe stabilirai il tuo DataSource oggetto all'avvio dell'app Web. Da lì memorizzeresti l'oggetto nel ServletContext oggetto passando a setAttribute . Context è il termine tecnico per "app web". Recupera chiamando getAttribute e trasmettere a DataSource .

In uno scenario aziendale, il DataSource possono essere archiviati in un'implementazione conforme a JNDI. Alcuni container servlet come Apache Tomcat possono fornire un'implementazione JNDI. Alcune organizzazioni utilizzano un server come un server LDAP. Registrazione e recupero del tuo DataSource oggetto con JNDI è trattato in molte altre domande e risposte su Stack Overflow.