I have below code
public void addNames(){
List<String> names = new ArrayList<String>
names.parallelStream().foreach(name->add(name));
}
private void add(String name){
SQLSession session = SQLSessionFactory.getSession(config);
Connection con=Session.openConnection();
con.insert(name);
con.commit;
con.close
}
The problem here is “name->add(name)” will execute for each name, there by I am opening and closing connections for each name. If I have millions of records then this is a problem.
I can’t open the connection outside “names.parallelStream().foreach(name->add(name, connection));” and pass it as parameter, because all the threads will get blocked on one connection object.
So, I want to obtain the connection per thread, How can I do this using
“names.parallelStream().foreach(name->add(name));” ?
I want do following per thread
Obtain connection
Insert
Insert
Insert —— N Inserts
Commit and close connection
If I am creating and starting a thread I can do this, How can we achieve this per thread using parallelStreams?
In short, I want the thread in parallelStream to obtain connection per thread and execute name->add(name) and once done the thread should commit and close the connection. Is this possible ?
I think you should not force the parallel stream for this. You will get the best performances if you do bulk inserts in chunks. Nevertheless, if you still want to do it, you should have a connection pool so each thread gets a connection and releases it after done its work. Your add method will look like:
private void add(String name){
Connection con=genCoonection(); //just take a connection from pool
con.insert(name);
con.commit;//commit after each record
}
You can find multiple examples on how to create and use a connection pool here:
How to establish a connection pool in JDBC?
Another option is to provide a custom ThreadLocal as described here and each thread will open the connection in a thread local. Then you shut down the thread pool and the connection will be closed as described here
Related
I have two threads in java application. The first thread runs the JDBC connection logic. The second one is listening to user's command.
public static void main ...
private Connection c; // this is JDBC connection visible to both Thread 1 and 2
Thread thread1 = new Thread(new Runnable() {
public void run() {
// logic to execute SQL statements on Connection c
}
);
Thread thread2 = new Thread(new Runnable() {
public void run() {
// Here i try to execute connection close on user's demand.
c.close();
// this command executes with no error,
// but the connection doesnt close immediately.
// The SQL statements in thread 1 somehow waits to finish,
// and only then will the connection stop.
// How to forcefully and abruptly stop the connection ?
}
);
How to forcefully and abruptly stop the connection ?
You could try calling c.close() in the 2nd thread, but:
JDBC connection objects are not thread-safe1, so the Java-side behavior is unspecified.
AFAIK, the JDBC spec doesn't say what will happen on the database server if a database connection is closed while a request is in progress. It is not clear if the request is terminated immediately or a bit later (with a transaction rollback or not).
So my advice would be don't do this. Find another way to do what you are trying to do.
(If you want advice on other ways, tell us the real problem you are trying to solve here rather than your roadblock with your attempted solution to the problem.)
1 - More precisely, they are not required to be thread-safe by the JDBC spec. They might actually be (sufficiently) thread-safe in some driver implementations, but ... only if the vendor docs say so. From various sources, at least Oracle DB and Derby support multiple threads sharing a logical JDBC connection, though they seem to support different models.
I don't think you can this way. But you can exit the whole JVM forcely:)
We are currently dealing with the function, that has to work partially with the database, and partially with a service, whice operations are time-consuming. So, generally speaking, here is a transactional method, that has a code like this:
Connection conn = null;
try {
conn = getConnection(); // This I get from the connection pool
Employee emp = queryDatabase(id);
// Point A - ??
Response resp = makeLongTimeServiceCall(emp);
// Point B - ??
anotherQueryDatabase(resp);
} catch (Exception e) {
throw e; // And this also rolls back the transaction
} finally {
// If conn is not closed, close it, so there would be no leaks
}
So the big question is - should I close the connection at point A and then get it again from the connection pool at point B, so that other servlets could use that connection while I interact with the service? My guess is that I should, but will this hurt my transaction?
In many circumstances: yes, closing and reopening the connection sounds good. However you need to understand the implication of doing them in two separate transactions (by closing and re-opening the connection you are inherently doing them in separate transaction).
If another user invokes an operation that changes the state of your data at Point B will the end result still be correct?
If you don't have a transaction you can close the connection and ask for a new connection when needed.
Remember that if you are using a connection pool closing a connection will not really close the connection, but only flag it as reusable by other threads.
Database connections shouldn't be left open. Open the connections just when you need to execute a query and close it as early as possible. So my solution is, YES.
if your application doesn't close connection properly may lead to some issues like the
connection pool maxing out.
Applications Not Properly Closing Connections:
When writing an application to use the WebSphere Application Server(WAS) datasource, the best way is fallowing get/use/close pattern.
1.get
-This is when the application makes a request to get a connection from the pool.
The application will first lookup the datasource name and then do a getConnection() call.
2.use
-This is when the application executes a query and waits for a response
3.close
-This is the final stage when the application has received the response from the database and is now done using that connection.
-The application should call close() in a finally block to close out the connection and return it to the free pool.
If your application does not follow this pattern, you may see connections staying open for long periods of time. This is especially seen when the application does not close the connection properly. After the response is received from the database, the application should be calling close in a finally block. If the application does not explicitly close the connection, that connection will stay open forever in WAS until that server is restarted. This is known as a connection leak. To resolve this type of issue, you will have to modify your application to close every connection
for further information: https://www.ibm.com/support/pages/common-reasons-why-connections-stay-open-long-period-time-websphere-application-server
I have a multithreaded application which uses OracleDriver.defaultConnection() to connect to the database.
This line of code is used in multiple code blocks which are accessed by different threads.
I am getting the error : Java Thread Deadlock detected
This is a sample piece of code :
private void function1() {
//something here
Connection conn = OracleDriver.defaultConnection();
// something here
conn.execute();
conn.close();
}
Second piece of code which is in a separate class :
private void function2() {
//something here
Connection conn = OracleDriver.defaultConnection();
// something here
conn.execute();
conn.close();
}
How do I make this connection "thread-safe"?
Also, I read that defaultConnection() returns a static object. So can this be caused due to the connection being closed by one thread while the other thread is using it?
I cannot use any connection method which requires me to input the database username and password.
Thanks in advance!
Java provides many ways for dealing with concurrency(synchronized, ReentrantLock, ReadWriteLock)
Considering the documentation which says:
The oracle.jdbc.OracleDriver class defaultConnection() method is an Oracle extension and always returns the same connection object.
Since it always returns the same connection object you can synchronize on it:
Connection conn = OracleDriver.defaultConnection();
synchronized (conn) {
// something here
conn.execute();
}
However you would need to remove all conn.close() calls due to:
If you do call the close() method, be aware of the following: All connection instances obtained through the defaultConnection() method, which actually all reference the same connection object, will be closed and unavailable for further use, with state and resource cleanup as appropriate. Executing defaultConnection() afterward would result in a new connection object.
Even though the connection object is closed, the implicit connection to the database will not be closed.
I am passing Resultset object to each thread. Each thread is connecting to the database and inserting data. Untill thread 110 it is working fine. After it crosses 111 thread it throws the above exception.
I am using oracle 11g.
My sample Thread code is:
class MyThreadClass implements Runnable
{
public Connection connection;
public Statement statement2;
public ResultSet rs2;
public String cookie;
public MyThreadClass(ResultSet rs1)
{
rs2=rs1;
}
public void run()
{
try
{
cookie=rs2.getString("COOKIE");
driver = "oracle.jdbc.driver.OracleDriver";
url = "jdbc:oracle:thin:#127.0.0.1:1521:xx";
/* connection
statement2.executeUpdate("INSERT INTO visit_header VALUES ('"+cookie+"')");
}
I am not getting how to handle this exception.
Your multi-threaded application is opening too many Connections/Sessions. Hence, the listener is dropping and blocking new connections for a while.
Check your DB resource usage first:
SELECT * FROM v$resource_limit WHERE resource_name IN ('processes','sessions');
Check to see if your MAX_UTILIZATION for either your Processes or Sessions is getting too close to the LIMIT_VALUE. If yes, you should either:
Use DB Connection pooling to share Connection objects between threads. Or,
Increase the number of processes/sessions that Oracle can service simultaneously.
Actually, Connection Pooling (#1) should always be done. An application cannot scale up otherwise. Check Apache Commons DBCP for details. For #2, open a new SQL*Plus session as SYSTEM and run:
ALTER system SET processes=<n-as-per-number-of-threads> scope=spfile;
to increase backend concurrency. Then RESTART the Database. IMPORTANT!
I guess the database just don't accept more connections from your host. If I understand your question right you are making maybe 100 threads which each connects to the database in short time. Maybe you don't even close the connection correctly, or the accesses are lasting so long that a huge amount of connections are opened. The database have a limit to which it accepts connections.
You should definitely reduce the number of connections by some clever technique. Maybe reduce the number of concurrent threads and/or use a connection pool.
Try this solution at your end. It worked for me.
Close the connection in try/catch block and just after closing the connection,
write-
Thread.sleep(1000);
In this case you can write it as-
finally {
try {
if (conn != null && !conn.isClosed())
{
conn.close();
Thread.sleep(1000);
}
}
catch (SQLException e) {
e.printStackTrace();}
}
The database connection is get like below
public Connection getDBConection(){
Context context = new InitialContext();
DataSource dataSource = (javax.sql.DataSource) context.lookup("java:myDataSource");
Connection conn = dataSource.getConnection();
}
For a userA, is each database request should call getDBConnection() once; but no need to control all request use the same connection?
That is, if userA has three database request, then userA should call getDBConnection() three times, and call Connection.closed() after used in each request?
If the userA call getDBConnection() three times (that is, call dataSource.getConnection() three times), is three connection created? Or it is unknown and controlled by weblogic?
I feel very chaos, is it true that there should be one new connection for one database request? or just call DataSource.getConnection() for each database request and the number of new connection created is controlled by web server, no need to think how many connection is actually created.
Every time you call DataSource.getConnection, the data source will retrieve a connection for you. It should be true that the returned connection is not being actively used by anyone else, but it is not necessarily a brand-new connection.
For example, if you use a connection pool, which is a very common practice, then when you call Connection.close, the connection is not actually closed, but instead returns to a pool of available connections. Then, when you call DataSource.getConnection, the connection pool will see if it has any spare connections lying around that it hasn't already handed out. If so, it will typically test that they haven't gone stale (usually by executing a very quick query against a dummy table). If not, it will return the existing connection to the caller. But if the connection is stale, then the connection pool will retrieve a truly new connection from the underlying database driver, and return that instead.
Typically, connection pools have a maximum number of real connections that they will keep at any one time (say, 50). If your application tries to request more than 50 simultaneous connections, DataSource.getConnection will throw an exception. Or in some implementations, it will block for a while until one becomes available, and then throw an exception after that time expires. For a sample implementation, have a look at Apache Commons DBCP.
Hopefully that answers your question!