PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Produza um objeto `DataSource` para Postgres JDBC, programaticamente

tl;dr


O PGSimpleDataSource classe empacotada com o driver JDBC de jdbc.postgresql.org implementa DataSource interface. Configure seus detalhes de conexão de banco de dados em um PGSimpleDataSource objeto e passar como um DataSource objeto.
PGSimpleDataSource ds = new PGSimpleDataSource() ;  
ds.setServerName( "localhost" );  
ds.setDatabaseName( "your_db_name_here" );   
ds.setUser( "scott" );       
ds.setPassword( "tiger" );   

Use esse objeto para fazer uma conexão com o banco de dados conforme necessário. Use a sintaxe conveniente de try-with-resources.
try
(
    Connection conn = ds.getConnection() ;
) 
{ … }

Implementação do driver JDBC


Seu driver JDBC pode fornecer a você uma implementação do DataSource interface.

Um objeto desta implementação contém as informações necessárias para fazer e configurar uma conexão com o banco de dados, como:
  • Nome e senha do usuário do banco de dados
  • Endereço IP e número da porta do servidor de banco de dados

Até três tipos de implementação fornecidos podem estar disponíveis:
  • Muitas vezes, essa implementação é um wrapper fino em torno do DriverManager . Cada vez que você chama DataSource::getConnection no objeto de tal implementação, você obtém uma nova conexão de banco de dados.
  • Como alternativa, uma implementação pode usar um pool de conexões abaixo para fornecer conexões já existentes. Essas conexões são entregues e devolvidas, como livros em uma biblioteca, para serem recicladas para uso repetido.
  • Uma implementação pode suportar a API de transações Java, suportando X/Open XA, para necessidades sofisticadas, como coordenar as transações em vários recursos, como bancos de dados e filas de mensagens. Não é tão comumente usado, então eu ignoro esse tipo aqui.

Driver de jdbc.postgresql.org


O driver gratuito de código aberto de jdbc.postgresql.org fornece todos os três tipos de DataSource implementação. Mas os autores não recomendam realmente usar seu tipo de pool de conexão na produção; se você quiser fazer um pool, use uma biblioteca de pool de conexões de terceiros. E estamos ignorando o tipo XA.

Então, vamos ver a implementação simples de conexão sempre atualizada de DataSource :org.postgresql.ds.PGSimpleDataSource

Configurando o objeto de fonte de dados


Instancie um objeto vazio e chame uma série de métodos setter para configurar para seu cenário de banco de dados específico. Os métodos setter são herdados de org.postgresql.ds.common.BaseDataSource .

Ainda não estamos fazendo upcast para a interface DataSource , para que possamos chamar os vários métodos setter. Consulte o código de exemplo e a discussão na página Fontes de dados 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?

Geralmente eu usaria esses métodos separados de setter. Como alternativa, você constrói uma String, uma URL, com as várias informações a serem definidas no DataSource em um golpe. Se você quiser seguir esse caminho, chame setUrl .

Isso cobre o básico. Mas você pode querer ou precisar de alguns dos outros setters. A maioria deles está configurando valores de propriedade Postgres no servidor. Todas as propriedades têm padrões inteligentes, mas você pode desejar substituir para situações especiais.
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 estiver usando TLS (anteriormente conhecido como SSL) para criptografar a conexão do banco de dados para proteger contra espionagem ou manipulação malévola, use vários setters para isso.

Para qualquer propriedade do Postgres sem um método setter específico, você pode chamar setProperty( PGProperty property, String value ) .

Você pode inspecionar ou verificar as configurações dessa fonte de dados chamando qualquer um dos muitos métodos getter.

Depois de configurar seu PGSimpleDataSource , você pode passar para o resto de sua base de código simplesmente como um DataSource objeto. Isso isola sua base de código do choque de mudar para outro DataSource implementação ou mudar para outro driver JDBC.
DataSource dataSource = ds ;  // Upcasting from concrete class to interface.
return dataSource ; 

Usando a fonte de dados


Usando um DataSource é totalmente simples, pois fornece apenas dois métodos, um par de variações em getConnection para obter uma Connection objeto para seu trabalho de banco de dados.
Connection conn = dataSource.getConnection() ; 

Quando terminar com sua Connection , a melhor prática é fechá-lo. Use uma sintaxe try-with-resources para fechar automaticamente a conexão ou feche-a explicitamente.
conn.close() ;

Tenha em mente que um DataSource não é realmente uma fonte de dados. Uma DataSource é realmente uma fonte para gerar/acessar conexões com o banco de dados. Na minha opinião, este é um nome impróprio, pois penso nele como ConnectionSource . O DataSource conversa com seu banco de dados apenas o tempo suficiente para entrar com nome de usuário e senha. Após esse login, você usa a Connection objeto para interagir com o banco de dados.

Armazenando seu DataSource


Uma vez configurado, você deseja manter esse DataSource objeto ao redor, em cache. Não há necessidade de reconfigurar repetidamente. A implementação deve ser escrita para ser thread-safe. Você pode chamar getConnection a qualquer hora de qualquer lugar.

Para um pequeno aplicativo Java simples, você pode armazená-lo como um campo em um singleton ou em uma variável global estática.

Para um aplicativo baseado em Servlet, como um Vaadin app, você criaria uma classe implementando ServletContextListener interface. Nessa classe, você estabeleceria seu DataSource objeto quando seu aplicativo da web está sendo iniciado. A partir daí você armazenaria o objeto no ServletContext objeto passando para setAttribute . Context é o termo técnico para 'aplicativo web'. Recupere chamando getAttribute e transmitindo para DataSource .

Em um cenário corporativo, o DataSource podem ser armazenados em uma implementação compatível com JNDI. Alguns contêineres Servlet, como o Apache Tomcat, podem fornecer uma implementação JNDI. Algumas organizações usam um servidor como um servidor LDAP. Registrando e recuperando seu DataSource objeto com JNDI é abordado em muitas outras perguntas e respostas no Stack Overflow.