In the JDBC driver for Postgres, is PGSimpleDataSource thread-safe?
That is, if I use a cached singleton instance of that class, can I pass it out to multiple threads? Each thread may be calling getConnection at the same moment. The documentation makes no mention of thread-safety.
I am trying to avoid both (a) making multi-threaded calls on a Connection and (b) using a connection pool, as discussed in the doc. I want a separate Connection for each servlet thread.
I'm assuming you won't be changing the data source configuration on multiple threads, because then it isn't thread-safe. You can inspect the source code yourself, on https://github.com/pgjdbc/pgjdbc, the specific code for getConnection is in BaseDataSource:
public Connection getConnection(String user, String password) throws SQLException {
try {
Connection con = DriverManager.getConnection(getUrl(), user, password);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Created a {0} for {1} at {2}", new Object[]{getDescription(), user, getUrl()});
}
return con;
} catch (SQLException e) {
LOGGER.log(Level.SEVERE, "Failed to create a {0} for {1} at {2}: {3}",
new Object[]{getDescription(), user, getUrl(), e});
throw e;
}
}
In other words, it is a thin wrapper around DriverManager. DriverManager itself is thread-safe, so then it becomes a question if org.postgresql.Driver is thread-safe. I don't have time to try to verify that, but lets just say it would be really surprising if that wasn't thread-safe (and otherwise world-wide applications would fail with all kinds of strange race-conditions, etc).
As a side note: PGSimpleDataSource does not provide connection pooling, you might want to consider whether that is right for your use case.
Related
I have a main class, a login class and a gui class.
Within my main I am creating a database connection using the Singleton pattern - only one instance of this connection.
I want to access the database connection from login, to verify users upon logging into the system.
My connection method within main:
/**
* Use the Singleton pattern to create one Connection
*/
private static Connection getConnection() {
if (conn != null) {
return conn;
}
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage() + " load driver error");
System.exit(0);
}
try {
//conn = DriverManager.getConnection(host);
conn = DriverManager.getConnection(host + "create=true", dbUsername, dbPassword);
} catch (SQLException e) {
displayErr("Get connection error: ", e);
System.exit(0);
}
return conn;
}
Now, I want to create a login method where I need to use the connection conn. The method is static and I cannot use conn.
I'm sure this is wrong but I've also tried making a public method which returns the connection conn and then tried calling that method from Main.
conn = Main.returnConnection();
What should I do in this situation? Pretty confused at how I'm supposed to model this.
Your approach is so primitive when it's compared with Connection Pooling. Connection pool means a pool that includes cached, reusable connections those can be used in future requests. As you said opening a connection for each user is an expensive process also giving a static connection for each user occurs conflictions. Connection pooling is the standart that should be used in these kind of circumstances.
connection = connectionPool.getConnection();
Upper code means get a connection from the pool, if all connections are already allocated, mechanism automatically creates a new one.
The most popular libraries are:
BoneCP
Apache DBCP
C3p0
I figured out the purpose of the Singleton pattern is to create one instance of something and allow it to be seen by everyone.
So I made it public static void instead and can now access the connection, without making a new one each time.
Correct me if I am wrong but this works fine.
I am developing a web application using JSP & Servlet (IDE: Eclipse, Database: Oracle10).
I have developed java class which returns a static connection, and that connection will be used by my entire web application.
public class DBConnection
{
private static Connection con = null;
static Connection getConnection(String str)
{
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection("MyValuesHere");
System.out.println("New instance of Connection is created for: "+str);
}
catch(ClassNotFoundException cnfe)
{
System.out.println("Error loading class!");
cnfe.printStackTrace();
}
catch(SQLException sqle)
{
System.out.println("Error connecting to the database!");
sqle.printStackTrace();
}
return con;
}//getConnection()
}//class
Above class is working fine. Then I have another 4 java classes for
Inserting
Updating
Deleting
Selecting
data from database using the above connection. So in those 4 classes I am getting connection which is created in my DBConnection class, and those four classes are also working fine. This four classes are used in my all Servlet's.
To get Connection in those 4 classes I am writing following line:
private static Connection con = DBConnection.getConnection("UpdateQuery.java");
But problem is that I want to share the same connection in all four classes, but connection is created separately in those 4 classes. So how should I share the same connection in those four classes? is there better way of doing this? and if I use this approach will there be any issues in web application because of sharing the connection for whole application?
You are (implicitly) trying to solve a non-trivial task.
Such things are normally done by the container - taking connections from a pool, then returning them back, reconnection etc...
If you use a fully functional applications server you'd better configure and use data sources.
If your server doesn't support data sources, do not mess up with saving connection into a private field. What for example happenes when your connection is lost? Your private variable will have a non-working connection. Do you have any recovery mechanism?
Your code will be much more robust if you get it in the beginning of the business operation and then close it.
Or try to find a professionally written library that supports connection pools - it will do pretty much the same as a classic container in handling a connection pool.
Or write it yourself, but it will be a separate task with many questions.
Looks like you wanted to turn Connection into a singleton but then forgot to check whether it's been instantiated already. In getConnection you could check if con is not null in the first place and return that instance right away. Only if con is still null, proceed with initialization.
You should save the created connection instance into a private static field in DBConnection, and when getConnection is called, you check if the field is null, then create the connection, then return it:
if (connection == null) {
connection = createConnection();
}
return connection;
where connection is a private static Connection connection field of DBConnection class.
However I strongly suggest to not use this approach as sharing a connection between concurrent threads will cause serious problems. I suggest to use connection pooling
i'm gonna create class that will operate on database. The class will have functions addRecord(), getAllRecords(), stuff like that. I'm looking for a good approach to design the class. Should i have to:
1) create new Connection for every function. Like this:
void readRecords(){
try {
Connection con = DriverManager.getConnection (connectionURL);
Statement stmt = con.createStatement();
ResultSet rs = stmd.executeQuery("select moviename, releasedate from movies");
while (rs.next())
System.out.println("Name= " + rs.getString("moviename") + " Date= " + rs.getString("releasedate");
}
catch (SQLException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
con.close();
}
}
or
2) it's better to have one connection as a memeber variable
class MyClass{
private Connection con;
public MyClass(){
con = DriverManager.getConnection (connectionURL);
}
}
and create just the statement for every function.
3) or something else...
Both approaches are bad. The first one won't allow you to implement proper transaction management, since you can't call several methods inside the same transaction. The latter one requires unnecessary creation of multiple objects.
The best approach would be to introduce a notion of the current connection, which can be obtained from some kind of transactional context. Basically, it should look like this:
beginTransaction(...); // Opens connection and starts transaction
readRecords(...); // Uses the current connection
addRecord(...);
...
commitTransaction(...); // Commits transaction and closes connection
The simpliest but not very elegant implementation is to open a Connection inside the calling method (which defines boundaries of the transaction) and pass it to your methods as a parameter.
More sophisticated solution is to create a static ThreadLocal storage for the current Connection, place it there when you start a transaction and obtain it from that storage inside your methods. Some frameworks implement this approach implicitly, for example, Spring Framework.
Note that connection pooling is completely orthogonal to these matters.
If there are frequent regular jdbc calls, then use a database connection pool.
Connection pooling is the way to go. The biggest reason is that on average the time it takes for the DB access (DML etc) is much smaller than the time it takes to create a connection and then close the connection. Additionally, don't forget to close your ResultSet, PreparedStatement and Connection variables after the transaction is done.
You can use tomcat or apache connection pooling classes.
THese classes are defined for example in the package
org.apache.commons.dbcp.*;
org.apache.tomcat.dbcp.dbcp.*;
where dbcp stands for database connection pooling.
I am working on an application where I need to connect N number of database systems [N ranges any where between 1 to 350].
The idea is - the user will be presented with a list of databases and will be asked to select any or all of the databases from the list.
Once the databases are selected, I need to connect to each of the database and execute a stored procedure.
I am planning to use plain old JDBC and obtain connection for each of them one a time [or by running them in multiple threads] and execute the store procedure and close the connection.
And all this should happen in a transaction. What is the best way to do this?
If not JDBC...any other efficient way?
Update -
The stored procedure is actually involved in running some sql - for example updating a column, grant permission for a user etc.
I'd create a threadpool with a reasonable maximum amount of threads, between ten and twenty threads maybe, with help of Executors#newFixedThreadPool() and invoke the separate DB connecting and SP executing tasks each as a Callable using ExecutorService#invokeAll(). You would like to play with the threadcount and profile which yields the best performance after all.
Each Callable implementation should take the connection details and SP name as constructor argument so that you can reuse the same implementation for different DB calls.
Update: OK, it's a webapplication. You don't want to waste threads. If it is supposed to be used by a single concurrent user, then you should really ensure that the threadpool is properly shutdown at end of request or at highest end of session. But if it is supposed to be used by multiple concurrent users, then you'd like to share the threadpool in the application scope. Also here, you need to ensure that it is properly shutdown when the webapp shuts down. The ServletContextListener is useful here.
If it is acceptable for you to use two connections, use connection pool c3p0 to manage them. To connect two databases I declare:
public Connection connection1;
public Connection connection2;
DataSource dataSource1;
DataSource dataSource2;
Then two similar methods:
public Connection dbConnect1() throws SQLException {
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass("com.mysql.jdbc.Driver");
} catch (PropertyVetoException e) {
}
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase1?autoReconnect=true");
cpds.setUser("myMYSQLServerLogin");
cpds.setPassword("myMYSQLServerPassword");
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
cpds.setMaxIdleTime(60);
cpds.setMaxStatements(100);
cpds.setPreferredTestQuery("SELECT 1");
cpds.setIdleConnectionTestPeriod(60);
dataSource1 = cpds;
connection1 = dataSource1.getConnection();
return connection1;
}
public Connection dbConnect2() throws SQLException {
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass("com.mysql.jdbc.Driver");
} catch (PropertyVetoException e) {
}
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase2?autoReconnect=true");
cpds.setUser("myMYSQLServerLogin");
cpds.setPassword("myMYSQLServerPassword");
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
cpds.setMaxIdleTime(60);
cpds.setMaxStatements(100);
cpds.setPreferredTestQuery("SELECT 1");
cpds.setIdleConnectionTestPeriod(60);
dataSource2 = cpds;
connection2 = dataSource2.getConnection();
return connection2;
}
As duffymo indicated in his comment, you will only be able to do transactions across multiple databases if you have a transaction coordinator and two phase commit.
For this you will need a J2EE stack that will handle JTA. If you are running in Tomcat or another container that does not have JTA, there are several options you can download and install.
Of course you will need to let the Container, not the database/stored procedure handle the transaction commits and rollbacks.
This sounds like a big mess, but it's your problem.
You need one connection pool per database. I wouldn't advise that you try to handle the connection lifecycle yourself. Let the app server do that for you.
If you want a group of databases to participate in one big transaction you'll have to use the JDBC XA drivers for all of them. You'll also need a JTA transaction manager to oversee the transaction for you.
The stored procedures cannot contain any logic to handle transactions; you have to let JTA do it.
You don't say what the stored procedure is doing. If it doesn't need to return anything, an alternative design might be JMS, a queue, and a listener pool. I'd be worried about threading if I were you. I'd find a way to let the container do that complicated stuff for meif I could.
public static Connection getconnection(String db,String host){
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://"+**Pass Your Host Here
Like Localhost**+"/"+Pass Your DB Name** +"?useUnicode=yes&characterEncoding=UTF-
8","root","root");
return con;
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
I'm still an undergrad just working part time and so I'm always trying to be aware of better ways to do things. Recently I had to write a program for work where the main thread of the program would spawn "task" threads (for each db "task" record) which would perform some operations and then update the record to say that it has finished. Therefore I needed a database connection object and PreparedStatement objects in or available to the ThreadedTask objects.
This is roughly what I ended up writing, is creating a PreparedStatement object per thread a waste? I thought static PreparedStatments could create race conditions...
Thread A stmt.setInt();
Thread B stmt.setInt();
Thread A stmt.execute();
Thread B stmt.execute();
A´s version never gets execed..
Is this thread safe? Is creating and destroying PreparedStatement objects that are always the same not a huge waste?
public class ThreadedTask implements runnable {
private final PreparedStatement taskCompleteStmt;
public ThreadedTask() {
//...
taskCompleteStmt = Main.db.prepareStatement(...);
}
public run() {
//...
taskCompleteStmt.executeUpdate();
}
}
public class Main {
public static final db = DriverManager.getConnection(...);
}
I believe it is not a good idea to share database connections (and prepared statements) between threads. JDBC does not require connections to be thread-safe, and I would expect most drivers to not be.
Give every thread its own connection (or synchronize on the connection for every query, but that probably defeats the purpose of having multiple threads).
Is creating and destroying PreparedStatement objects that are always the same not a huge waste?
Not really. Most of the work happens on the server, and will be cached and re-used there if you use the same SQL statement. Some JDBC drivers also support statement caching, so that even the client-side statement handle can be re-used.
You could see substantial improvement by using batched queries instead of (or in addition to) multiple threads, though. Prepare the query once, and run it for a lot of data in a single big batch.
The threadsafety is not the issue here. All looks syntactically and functionally fine and it should work for about half a hour. Leaking of resources is however the real issue here. The application will crash after about half a hour because you never close them after use. The database will in turn sooner or later close the connection itself so that it can claim it back.
That said, you don't need to worry about caching of preparedstatements. The JDBC driver and the DB will take care about this task. Rather worry about resource leaking and make your JDBC code as solid as possible.
public class ThreadedTask implements runnable {
public run() {
Connection connection = null;
Statement statement = null;
try {
connection = DriverManager.getConnection(url);
statement = connection.prepareStatement(sql);
// ...
} catch (SQLException e) {
// Handle?
} finally {
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
}
}
To improve connecting performance, make use of a connection pool like c3p0 (this by the way does not mean that you can change the way how you write the JDBC code; always acquire and close the resources in the shortest possible scope in a try-finally block).
You're best to use a connection pool and get each thread to request a connection from the pool. Create your statements on the connection you're handed, remembering to close it and so release it back to the pool when you're done. The benefit of using the pool is that you can easily increase the number of available connections should you find that thread concurrency is becoming an issue.