What is the difference between OracleDataSourceFactory, OracleConnectionPoolDataSource and OracleDataSource? What are the different situations you would use them in?
The reason why there is a OracleDataSource and a OracleConnectionPoolDataSource is because the JDBC standard defines two types of connections:
java.sql.Connection which are commonly used in JDBC applications
javax.sql.PooledConnection are not directly used by applications by by connection pool vendors
OracleDataSource is a factory of java.sql.Connection objects and that's the datasource that's widely used by applications. On the other hand OracleConnectionPoolDataSource is used for javax.sql.PooledConnection and is used only in connection cache implementations (UCP for example).
You can safely ignore OracleDataSourceFactory which is an artifact to build DataSource objects that Oracle no longer promotes.
With the 19c Oracle JDBC driver, you would instantiate a datasource like this:
oracle.jdbc.datasource.OracleDataSource ds = oracle.jdbc.pool.OracleDataSource();
or, if you're using the replay driver (for Application Continuity):
oracle.jdbc.datasource.OracleDataSource ds = oracle.jdbc.replay.OracleDataSourceImpl();
Related
I'm confused about the difference between DataSource and SessionFactory.
I think SessionFactory is a manager for retrieve Sessions (which are in fact connections to a database I guess).
DataSource has the method getConnection()
"Attempts to establish a connection with the data source that this DataSource object represents."
It means a DataSource object always works directly with the database?
If I have a pool of connections, DataSource will ask to the pool for a connection? Or will it try to get another connection to the database.
Are in fact DataSource and SessionFactory the same? Both try to give sessions/connections?
Datasource maintains the pool of connections, establishes the connection, knows how to connect etc.,
User configures data source either in the server(like websphere/weblogic) or in the spring/hibernate configuration file. Either way you give the handle of this data source to the sessionfactory during the app startup.
SessionFActory is an interface which hides all the details like opening the connection / closing the connections. Through out your development time you dont worry about these small things like loading driver/closing connection/opening etc., so you can concentrate on business logic/other important stuff.
I have a basic question about the Tomcat 7 JDBC Connection Pool: is a separate pool created for each separate database (i.e., URL)? Or is a single pool created that holds open connections from any number of different databases?
For example, if I open connections to databases A and B by doing this:
PoolProperties poolProperties = new PoolProperties();
poolProperties.setDriverClassName("org.postgresql.Driver");
poolProperties.setUrl("jdbc:postgresql://myserver/db_a");
poolProperties.setInitialSize(1);
poolProperties.setMaxActive(10);
poolProperties.setMaxIdle(1);
poolProperties.setMinIdle(0);
and then this:
PoolProperties poolProperties = new PoolProperties();
poolProperties.setDriverClassName("org.postgresql.Driver");
poolProperties.setUrl("jdbc:postgresql://myserver/db_b");
poolProperties.setInitialSize(1);
poolProperties.setMaxActive(10);
poolProperties.setMaxIdle(1);
poolProperties.setMinIdle(0);
Have I just created one pool with a maxActive of 10, or two pools, each with a maxActive of 10? If it's one pool, what if I had changed maxActive to, say, 30 when opening the connection for database B? Does the first call to setMaxActive win, or does the second call override, or does this cause a separate pool to be created?
Okay, I did some digging and figured this out myself. (Thanks for the many kind folks on the tomcat-users mailing list!)
JB Nizet is right: if you are creating Tomcat database connection pools from Java code, each DataSource you instantiate literally is/represents a separate connection pool. This was surprising to me; coming from a .NET background, I assumed the Tomcat connection pooling would work like SqlServer/ADO.NET connection pooling: if you use two identical connection strings to get two database connections, these will both come from the same connection pool. However, in Tomcat, when instantiating DataSource objects from Java code, each new DataSource instance is a whole new connection pool. So, if you want to persist these connection pools across JAX-RS web service calls, for example, you need to build your own database-pool (DataSource) cache, put the DataSource instances (one per database) into it, and store it in an object that JAX-RS will persist across web service calls. I just did this, and it is working fine.
btw, Tomcat database connection pooling does offer functionality similar to SqlServer/ADO.NET connection pooling, you just have to use JNDI resources to create your DataSource instances. (In my case this is not an option, since databases are created dynamically in my application, and JNDI definitions are generally created from config files that Tomcat reads at startup.)
What is the difference between javax.sql.DataSource and javax.sql.ConnectionPoolDataSource? I don't know which resource type to use when I am creating a connection pool in GlassFish for MySQL.
ConnectionPoolDataSource is just a DataSource (as it inherit's CommonDataSource which is also inherited by DataSource) with capability of Connection Pooling -
you asked : I don't know which resource type to use
It depend's on your application, many database drivers take a long time to create a new connection with database, If your application is going to create too many connection's (very frequently). use connection pooling.
How can I get the current Connection object for an Oracle database? I'm using the JDBC module in Spring 3.0.5.
Obtain the Connection from the DataSource bean.
You can access the dataSource by using Spring dependency injection to inject it into your bean, or by accessing ApplicationContext statically:
DataSource ds = (DataSource)ApplicationContextProvider.getApplicationContext().getBean("dataSource");
Connection c = ds.getConnection();
Just an Info :
I am using Spring JDBC Template, which holds the current connection object for me, which can be received as follows.
Connection con;
con = getJdbcTemplate().getDataSource().getConnection();
Use DataSourceUtils.getConnection().
It returns connection associated with the current transaction, if any.
I'm not sure if this method was available when this question was originally posted, however, it seems the preferred way to do it in the latest version of Spring is with JdbcTemplate and PreparedStatementCreator. See https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html#query-org.springframework.jdbc.core.PreparedStatementCreator-org.springframework.jdbc.core.PreparedStatementSetter-org.springframework.jdbc.core.ResultSetExtractor- or any of the other query methods that take a PreparedStatementCreator as the first param:
jdbcTemplate.query(con -> {
// add required logic here
return con.prepareStatement("sql");
}, rs -> {
//process row
});
This has the advantage over the other provided answers (DataSourceUtils.getConnection() or jdbcTemplate.getDataSource().getConnection() as a new connection is not allocated, it uses the same connection management it would as calling any of the other jdbcTemplate querying methods. You also therefore do not need to worry about closing / releasing the connection, since spring will handle it.
I'm trying to follow Sun's JDBC tutorial at http://java.sun.com/docs/books/tutorial/jdbc/basics/connecting.html
It gives the following example code:
DataSource ds = (DataSource) org.apache.derby.jdbc.ClientDataSource()
ds.setPort(1527);
ds.setHost("localhost");
ds.setUser("APP")
ds.setPassword("APP");
Connection con = ds.getConnection();
This code doesn't compile because the DataSource interface has none of these methods, except for the getConnection() method invoked last.
(Here's the javadoc: http://java.sun.com/javase/6/docs/api/javax/sql/DataSource.html)
What am I missing?
Edit:
I'm actually trying to connect to MySQL (com.mysql.jdbc) and I can't find the javadoc for that. I'll accept an answer that points me to either:
1) documentation for com.mysql.jdbc regarding a DataSource that I can understand, or
2) gives an example to follow for what the tutorial's code should be, for any database.
One thing you might want to look at is the Commons DBCP project. It provides a BasicDataSource that is configured fairly similarly to your example. To use that you need the database vendor's JDBC JAR in your classpath and you have to specify the vendor's driver class name and the database URL in the proper format.
Edit:
If you want to configure a BasicDataSource for MySQL, you would do something like this:
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("username");
dataSource.setPassword("password");
dataSource.setUrl("jdbc:mysql://<host>:<port>/<database>");
dataSource.setMaxActive(10);
dataSource.setMaxIdle(5);
dataSource.setInitialSize(5);
dataSource.setValidationQuery("SELECT 1");
Code that needs a DataSource can then use that.
DataSource is vendor-specific, for MySql you could use MysqlDataSource which is provided in the MySql Java connector jar:
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setDatabaseName("xyz");
dataSource.setUser("xyz");
dataSource.setPassword("xyz");
dataSource.setServerName("xyz.yourdomain.com");
Basically in JDBC most of these properties are not configurable in the API like that, rather they depend on implementation. The way JDBC handles this is by allowing the connection URL to be different per vendor.
So what you do is register the driver so that the JDBC system can know what to do with the URL:
DriverManager.registerDriver((Driver) Class.forName("com.mysql.jdbc.Driver").newInstance());
Then you form the URL:
String url = "jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]"
And finally, use it to get a connection:
Connection c = DriverManager.getConnection(url);
In more sophisticated JDBC, you get involved with connection pools and the like, and application servers often have their own way of registering drivers in JNDI and you look up a DataSource from there, and call getConnection on it.
In terms of what properties MySQL supports, see here.
EDIT: One more thought, technically just having a line of code which does Class.forName("com.mysql.jdbc.Driver") should be enough, as the class should have its own static initializer which registers a version, but sometimes a JDBC driver doesn't, so if you aren't sure, there is little harm in registering a second one, it just creates a duplicate object in memeory.
use MYSQL as Example:
1) use database connection pools: for Example: Apache Commons DBCP , also, you need basicDataSource jar package in your classpath
#Bean
public BasicDataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/gene");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
2)use JDBC-based Driver it is usually used if you don't consider connection pool:
#Bean
public DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/gene");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
I think the example is wrong - javax.sql.DataSource doesn't have these properties either. Your DataSource needs to be of the type org.apache.derby.jdbc.ClientDataSource, which should have those properties.
The javadoc for DataSource you refer to is of the wrong package. You should look at javax.sql.DataSource. As you can see this is an interface. The host and port name configuration depends on the implementation, i.e. the JDBC driver you are using.
I have not checked the Derby javadocs but I suppose the code should compile like this:
ClientDataSource ds = org.apache.derby.jdbc.ClientDataSource()
ds.setHost etc....
For postgres, the below works. I actually used it in integ tests. I guess there should be some more consideration for production usage.
PGSimpleDataSource ds = new PGSimpleDataSource() ;
ds.setServerName( "localhost" );
ds.setDatabaseName( "your_db_name_here" );
ds.setUser( "scott" );
ds.setPassword( "tiger" );
The class is bundled in the postgres jdbc driver.
The original stackoverflow post i followed: https://stackoverflow.com/a/45091982/3877642