以编程方式为Postgres JDBC生成一个"DataSource"对象 [英] Produce a `DataSource` object for Postgres JDBC, programmatically

查看:91
本文介绍了以编程方式为Postgres JDBC生成一个"DataSource"对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JDBC教程建议使用 与数据源对象连接 页面:

DataSource对象…获得与数据源的连接的首选方法.

如何为与Postgres的 JDBC 连接获得这样的对象?我有一个JDBC驱动程序.

现在,我不想像 this 解决方案

JDBC驱动程序的实现

您的 JDBC驱动程序可以为您提供 DriverManager .每次调用 DataSource::getConnection 在这种实现的对象上,您将获得新的数据库连接.

  • 或者,一个实现可能在下面使用连接池来提供已经存在的连接.分发这些连接,然后将它们重新签回,就像在图书馆中的书一样,可以回收再利用.
  • 实施可能支持 Java交易API ,并支持 jdbc.postgresql.org 的开源免费驱动程序提供了以下三种类型的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非常简单,因为它仅提供两种方法,即 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 call DataSource::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屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆