以编程方式为 Postgres JDBC 生成一个“DataSource”对象
Produce a `DataSource` object for Postgres JDBC, programmatically
JDBC Tutorial recommends using a DataSource
object to obtain database connections rather than using the DriverManager
class. To quote the Connecting with DataSource Objects 页面:
DataSource
objects … the preferred means of getting a connection to a data source.
我如何获得这样一个 JDBC 连接到 Postgres 的对象?我有一个 JDBC 驱动程序。
现在,我不想 fiddle 像 this or 那样使用 JNDI。
我可以在我的 Java 应用程序中以编程方式实例化 DataSource
吗?还是我必须自己实现 DataSource
接口?
tl;博士
PGSimpleDataSource
class 与来自 jdbc.postgresql.org 的 JDBC driver 捆绑在一起实现了 DataSource
接口。在 PGSimpleDataSource
object 中配置您的数据库连接详细信息,并作为 DataSource
object.
传递
PGSimpleDataSource ds = new PGSimpleDataSource() ;
ds.setServerName( "localhost" );
ds.setDatabaseName( "your_db_name_here" );
ds.setUser( "scott" );
ds.setPassword( "tiger" );
根据需要使用 object 连接到数据库。使用方便的 try-with-resources 语法。
try
(
Connection conn = ds.getConnection() ;
)
{ … }
JDBC driver 的实现
您的 JDBC driver may provide for you an implementation of the DataSource
界面。
此实现的 object 包含建立和配置数据库连接所需的信息,例如:
- 数据库用户名和密码
- 数据库服务器的IP地址和端口号
最多可以使用三种提供的实现:
- 通常这样的实现是围绕 object 上的
DriverManager
. Each time you call DataSource::getConnection
的薄包装,您将获得一个新的数据库连接。
- 或者,一个实现可能在下面使用 connection pool 来提供 already-existing 连接。这些连接被分发并重新签入,就像图书馆中的书籍一样,可以回收重复使用。
- 实现可能支持 Java Transaction API, supporting X/Open XA,以满足复杂的需求,例如协调跨多个资源(如数据库和消息队列)的事务。不太常用,所以我在这里忽略这种类型。
Driver 来自 jdbc.postgresql.org
open-source free-of-cost driver 来自 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.
那么让我们看一下 DataSource
的简单 fresh-connection-each-time 实现:org.postgresql.ds.PGSimpleDataSource
配置数据源object
实例化一个空的object,然后调用一系列setter methods to configure for your particular database scenario. The setter methods are inherited from org.postgresql.ds.common.BaseDataSource
.
我们还没有向上转换到接口 DataSource
,以便我们可以调用 various setter methods. See example code and discussion on the Data Sources and 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?
通常我会使用这些单独的 setter 方法。或者,您构造一个字符串,一个 URL,其中包含要一次性设置在 DataSource
上的各种信息。如果您想走那条路,请致电 setUrl
.
这涵盖了基础知识。但是您可能想要或需要其他一些 setter。其中大部分是在服务器上设置 Postgres property 值。这些属性都有智能默认值,但您可能希望在特殊情况下覆盖。
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)加密数据库连接以防止窃听或恶意操作,请为此使用多个 setter。
对于没有特定 setter 方法的任何 Postgres 属性,您可以调用 setProperty( PGProperty property, String value )
.
您可以通过调用许多 getter 方法中的任何一种来检查或验证此数据源上的设置。
配置 PGSimpleDataSource
后,您可以将代码库的其余部分作为 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 ;
使用数据源
使用 DataSource
非常简单,因为它只提供两种方法,一对 getConnection
to get a Connection
object 的变体用于您的数据库工作。
Connection conn = dataSource.getConnection() ;
完成 Connection
后,最佳做法是确保将其关闭。使用 try-with-resources syntax 自动关闭连接,或显式关闭它。
conn.close() ;
请记住,DataSource
实际上不是数据源。 DataSource
实际上是 generating/accessing 数据库连接的来源。在我看来,这是用词不当,因为我认为它是 ConnectionSource
。 DataSource
与您的数据库对话的时间仅够 sign-in 使用用户名和密码。在sign-in之后,你使用Connection
object与数据库进行交互。
存储您的DataSource
配置完成后,您希望将 DataSource
object 保留在缓存中。无需重复re-configure。 implementation should be written to be thread-safe。您可以随时随地拨打getConnection
。
对于一个简单的小 Java 应用程序,您可能希望将其存储为单例或静态全局变量中的字段。
换一个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
是 'web app' 的技术术语。通过调用 getAttribute
并强制转换为 DataSource
.
进行检索
在企业场景下,DataSource
可能存储在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中。 Stack Overflow 上的许多其他问答中都介绍了使用 JNDI 注册和检索 DataSource
object。
JDBC Tutorial recommends using a DataSource
object to obtain database connections rather than using the DriverManager
class. To quote the Connecting with DataSource Objects 页面:
DataSource
objects … the preferred means of getting a connection to a data source.
我如何获得这样一个 JDBC 连接到 Postgres 的对象?我有一个 JDBC 驱动程序。
现在,我不想 fiddle 像 this or
我可以在我的 Java 应用程序中以编程方式实例化 DataSource
吗?还是我必须自己实现 DataSource
接口?
tl;博士
PGSimpleDataSource
class 与来自 jdbc.postgresql.org 的 JDBC driver 捆绑在一起实现了 DataSource
接口。在 PGSimpleDataSource
object 中配置您的数据库连接详细信息,并作为 DataSource
object.
PGSimpleDataSource ds = new PGSimpleDataSource() ;
ds.setServerName( "localhost" );
ds.setDatabaseName( "your_db_name_here" );
ds.setUser( "scott" );
ds.setPassword( "tiger" );
根据需要使用 object 连接到数据库。使用方便的 try-with-resources 语法。
try
(
Connection conn = ds.getConnection() ;
)
{ … }
JDBC driver 的实现
您的 JDBC driver may provide for you an implementation of the DataSource
界面。
此实现的 object 包含建立和配置数据库连接所需的信息,例如:
- 数据库用户名和密码
- 数据库服务器的IP地址和端口号
最多可以使用三种提供的实现:
- 通常这样的实现是围绕 object 上的
DriverManager
. Each time you callDataSource::getConnection
的薄包装,您将获得一个新的数据库连接。 - 或者,一个实现可能在下面使用 connection pool 来提供 already-existing 连接。这些连接被分发并重新签入,就像图书馆中的书籍一样,可以回收重复使用。
- 实现可能支持 Java Transaction API, supporting X/Open XA,以满足复杂的需求,例如协调跨多个资源(如数据库和消息队列)的事务。不太常用,所以我在这里忽略这种类型。
Driver 来自 jdbc.postgresql.org
open-source free-of-cost driver 来自 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.
那么让我们看一下 DataSource
的简单 fresh-connection-each-time 实现:org.postgresql.ds.PGSimpleDataSource
配置数据源object
实例化一个空的object,然后调用一系列setter methods to configure for your particular database scenario. The setter methods are inherited from org.postgresql.ds.common.BaseDataSource
.
我们还没有向上转换到接口 DataSource
,以便我们可以调用 various setter methods. See example code and discussion on the Data Sources and 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?
通常我会使用这些单独的 setter 方法。或者,您构造一个字符串,一个 URL,其中包含要一次性设置在 DataSource
上的各种信息。如果您想走那条路,请致电 setUrl
.
这涵盖了基础知识。但是您可能想要或需要其他一些 setter。其中大部分是在服务器上设置 Postgres property 值。这些属性都有智能默认值,但您可能希望在特殊情况下覆盖。
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)加密数据库连接以防止窃听或恶意操作,请为此使用多个 setter。
对于没有特定 setter 方法的任何 Postgres 属性,您可以调用 setProperty( PGProperty property, String value )
.
您可以通过调用许多 getter 方法中的任何一种来检查或验证此数据源上的设置。
配置 PGSimpleDataSource
后,您可以将代码库的其余部分作为 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 ;
使用数据源
使用 DataSource
非常简单,因为它只提供两种方法,一对 getConnection
to get a Connection
object 的变体用于您的数据库工作。
Connection conn = dataSource.getConnection() ;
完成 Connection
后,最佳做法是确保将其关闭。使用 try-with-resources syntax 自动关闭连接,或显式关闭它。
conn.close() ;
请记住,DataSource
实际上不是数据源。 DataSource
实际上是 generating/accessing 数据库连接的来源。在我看来,这是用词不当,因为我认为它是 ConnectionSource
。 DataSource
与您的数据库对话的时间仅够 sign-in 使用用户名和密码。在sign-in之后,你使用Connection
object与数据库进行交互。
存储您的DataSource
配置完成后,您希望将 DataSource
object 保留在缓存中。无需重复re-configure。 implementation should be written to be thread-safe。您可以随时随地拨打getConnection
。
对于一个简单的小 Java 应用程序,您可能希望将其存储为单例或静态全局变量中的字段。
换一个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
是 'web app' 的技术术语。通过调用 getAttribute
并强制转换为 DataSource
.
在企业场景下,DataSource
可能存储在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中。 Stack Overflow 上的许多其他问答中都介绍了使用 JNDI 注册和检索 DataSource
object。