以编程方式为Postgres JDBC生成一个"DataSource"对象 [英] Produce a `DataSource` object for Postgres JDBC, programmatically
问题描述
DataSource
对象…获得与数据源的连接的首选方法.
如何为与Postgres的 JDBC 连接获得这样的对象?我有一个JDBC驱动程序.
JDBC驱动程序的实现
您的 JDBC驱动程序可以为您提供 DriverManager
.每次调用 DataSource::getConnection
在这种实现的对象上,您将获得新的数据库连接.
DataSource
实现.但是作者不建议实际使用其连接池类型生产中;如果要进行池化,请使用第三方连接池库.而且,我们忽略了 XA类型.>
因此,让我们看一下DataSource
的简单的每次连接新实现:设置方法以针对您的特定条件进行配置数据库方案. setter方法继承自 org.postgresql.ds.common.BaseDataSource
.
我们尚未转换到接口DataSource
,因此我们可以调用数据源和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?
通常,我将使用这些单独的设置方法.另外,您可以构造一个URL字符串,其中包含要在DataSource
上进行一次设置的各种信息.如果您想走那条路,请致电 setUrl
.
涵盖了基础知识.但是您可能需要或需要其他一些设置器.其中大多数都在服务器上设置 Postgres属性值.这些属性均具有智能默认值,但是在特殊情况下您可能希望覆盖这些属性.
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.
如果使用 TLS (以前称为SSL)来加密数据库连接,以防止受到攻击窃听或恶意操纵,为此使用几个设置器.
对于没有特定设置方法的任何Postgres属性,您可以调用 DataSource
对象.这使您的代码库免受更改为另一个DataSource
实现或更改为另一个JDBC驱动程序的冲击. >.
DataSource dataSource = ds ; // Upcasting from concrete class to interface.
return dataSource ;
使用数据源
使用DataSource
非常简单,因为它仅提供两种方法,即 Connection
对象用于数据库工作.
Connection conn = dataSource.getConnection() ;
完成Connection
后,最佳实践是确保将其关闭.使用 try-with-resources语法自动关闭连接,或显式关闭它.
conn.close() ;
请记住,DataSource
实际上不是数据源. DataSource
实际上是用于生成/访问数据库连接的源.在我看来,这是用词不当,因为我认为它是ConnectionSource
. DataSource
与您的数据库对话的时间仅够用用户名和密码登录.登录后,您可以使用Connection
对象与数据库进行交互.
存储您的DataSource
配置完成后,您要保留该DataSource
对象,并对其进行缓存.无需重复配置. 实现应编写为线程安全的.您可以随时随地致电getConnection
.
对于一个简单的小型Java应用程序,您可能希望将其存储为单例或静态全局变量中的字段.
对于基于 Servlet 的应用程序,例如 ServletContext
对象,方法是传递到 setAttribute
. Context
是网络应用"的技术术语.通过调用getAttribute
并强制转换为DataSource
进行检索.
在企业场景中,DataSource
可以存储在 JNDI 兼容的环境中执行.一些 Servlet容器,例如 LDAP服务器.注册和使用JNDI检索DataSource
对象在其他许多问题中也涉及到.堆栈溢出的答案.
The JDBC Tutorial recommends using a DataSource
object to obtain database connections rather than using the DriverManager
class. To quote the Connecting with DataSource Objects page:
DataSource
objects … the preferred means of getting a connection to a data source.
How do I get such an object for a JDBC connection to Postgres? I have a JDBC driver in place.
Right now, I do not want to fiddle around with JNDI like this or this.
Can I instantiate a DataSource
programmatically within my Java app? Or must I implement that DataSource
interface myself?
JDBC driver’s implementation
Your JDBC driver may provide for you an implementation of the DataSource
interface.
An object of this implementation contains the information needed to make and configure a connection to the database, such as:
- Name & password of database user
- IP address & port number of database server
Up to three kinds of implementation provided may be available:
- Often such an implementation is a thin wrapper around the
DriverManager
. Each time you callDataSource::getConnection
on the object of such an implementation, you get a fresh database connection. - Alternatively, an implementation may be using a connection pool underneath to supply already-existing connections. These connections are handed out and checked back in, like books in a library, to be recycled for repeated use.
- An implementation may support the Java Transaction API, supporting X/Open XA, for sophisticated needs like coordinating the transactions across multiple resources such as databases and message queues. Not as commonly used, so I ignore this type here.
Driver from jdbc.postgresql.org
The open-source free-of-cost driver from jdbc.postgresql.org provides all three types of DataSource
implementation. But the authors do not recommend actually using their connection pool type in production; if you want pooling, use a third-party connection pooling library. And we are ignoring the XA type.
So let's look at the simple fresh-connection-each-time implementation of DataSource
: org.postgresql.ds.PGSimpleDataSource
Configuring the data source object
Instantiate an empty object, then call a series of setter methods to configure for your particular database scenario. The setter methods are inherited from org.postgresql.ds.common.BaseDataSource
.
We are not yet upcasting to the interface DataSource
, so that we can call the various setter methods. See example code and discussion on the Data Sources and JNDI page.
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?
Generally I would use these separate setter methods. Alternatively, you construct a String, a URL, with the various pieces of info to be set on the DataSource
in one stroke. If you want to go that route, call setUrl
.
That covers the basics. But you might want or need some of the other setters. Most of these are setting Postgres property values on the server. The properties all have smart defaults, but you may wish to override for special situations.
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.
If using TLS (formerly known as SSL) to encrypt the database connection to protect against eavesdropping or malevolent manipulation, use several setters for that.
For any Postgres property without a specific setter method, you may call setProperty( PGProperty property, String value )
.
You can inspect or verify settings on this data source by calling any of the many getter methods.
After configuring your PGSimpleDataSource
, you can pass off to the rest of your codebase as simply a DataSource
object. This insulates your codebase from the shock of changing to another DataSource
implementation or changing to another JDBC driver.
DataSource dataSource = ds ; // Upcasting from concrete class to interface.
return dataSource ;
Using the data source
Using a DataSource
is utterly simple as it provides for only two methods, a pair of variations on getConnection
to get a Connection
object for your database work.
Connection conn = dataSource.getConnection() ;
When finished with your Connection
, best practice is to be sure to close it. Either use a try-with-resources syntax to automatically close the connection, or explicitly close it.
conn.close() ;
Keep clear in your mind that a DataSource
is not actually a data source. A DataSource
is really a source for generating/accessing connections to the database. To my mind, this is a misnomer, as I think of it as ConnectionSource
. The DataSource
talks to your database only long enough to sign-in with user name and password. After that sign-in, you use the Connection
object to interact with the database.
Storing your DataSource
Once configured, you want to keep that DataSource
object around, cached. No need to re-configure repeatedly. The implementation should be written to be thread-safe. You may call getConnection
at anytime from anywhere.
For a simple little Java app, you may want to store it as a field on a singleton or in a static global variable.
For a Servlet-based app such as a Vaadin app, you would create a class implementing ServletContextListener
interface. In that class your would establish your DataSource
object when your web app is launching. From there you would store the object in the ServletContext
object by passing to setAttribute
. Context
is the technical term for 'web app'. Retrieve by calling getAttribute
and casting to DataSource
.
In an enterprise scenario, the DataSource
may be stored in a JNDI-compliant implementation. Some Servlet containers such as Apache Tomcat may provide a JNDI implementation. Some organizations use a server such as an LDAP server. Registering & retrieving your DataSource
object with JNDI is covered in many other Questions & Answers on Stack Overflow.
这篇关于以编程方式为Postgres JDBC生成一个"DataSource"对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!