create another connection in transaction mysql - java

I want know if it is possibile create two connection different connections in one transaction, So suppose to have this code( I do a create operation in table "employe" and I create a log in table "log"):
try {
InitialContext initialContext = new InitialContext();
DataSource datasource = (DataSource) initialContext.lookup("java:/comp/env/jdbc/postgres");
Connection connection_db= datasource.getConnection();
PreparateStatement p1 //Preparate statement to put the employe parameter
connessione_db.setAutoCommit(false);
connessione_db.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
p1.execute();
//This create another connect
LOGStatic.createLog("CREATE EMPLOYE");
connessione_db.commit();
connessione_db.setAutoCommit(true);
}catch(....){
connection_db.rollback();
}
This is the method LOGStatic.createLog("CREATE EMPLOYE");
public static void creaLogException(String messaggio) {
Connection connection_db= null;
InitialContext initialContext;
try {
initialContext = new InitialContext();
DataSource datasource = (DataSource) initialContext.lookup("java:/comp/env/jdbc/postgres");
connection_db= datasource.getConnection();
// the code continues with the save operation
} catch (NamingException n) {
}
// actual jndi name is "jdbc/postgres"
catch (SQLException s) {
}
My question if is it possible this behavior and there aren't problem with commit and rollback operatio or it is not possible to have another connection?
Anyone can help

At least in JDBC, the transaction is tightly coupled with the Connection.
In a Java EE server, if you are writing session beans, then the transaction will be managed my the server. So, in that case, you could call several methods, and the transaction will follow the method calls.
In JDBC the simple solution is to not close the connection, but to pass it around to different methods as an input parameter.
But, be very careful, not closing connections is almost a sure shot way of getting to OutOfMemoryError.
(Instead of passing around the connection as input parameters to various methods, you could use ThreadLocal. But that is another source of memory leak, if you don't clean up ThreadLocal variables.)
For more information on how transaction-lifecycle and Connection are tied in JDBC, refer this: How to start a transaction in JDBC?
Note: Even in JavaEE nested transaction is not possible as nested transactions is not supported in JTA.
Passing the connection around:
public static void createEmployee(){
InitialContext initialContext = new InitialContext();
DataSource datasource = (DataSource) initialContext.lookup("java:/comp/env/jdbc/postgres");
Connection connection_db= datasource.getConnection();
try {
connessione_db.setAutoCommit(false);
connessione_db.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
PreparateStatement p1 //Preparate statement to put the employe parameter
p1.execute();
//This create another connect
createLog("CREATE EMPLOYE", connessione_db);
connessione_db.commit();
//connessione_db.setAutoCommit(true); //No need
}catch(....){
try{ connection_db.rollback(); }catch(Exception e){ /*You can also check some flags to avoid exception*/ }
}finally{
try{ connection_db.close(); }catch(Exception e){ /*Safe to ignore*/ }
}
}
public static void createLog(String messaggio, Connection connection_db) {
try {
// the code continues with the save operation
} catch (SQLException s) {
}
}

Related

How to manage DSLContext in jooq? (close connection)

This is how I implement each jooq query that i want.
UtilClass{
//one per table more or less
static void methodA(){
//my method
Connection con = MySQLConnection.getConexion(); //open
DSLContext create = DSL.using(con, SQLDialect.MYSQL); //open
/* my logic and jooq querys */ //The code !!!!!!!
try {
if ( con != null )
con.close(); //close
} catch (SQLException e) {
} //close
con=null; //close
create=null; //close
}
}
Am I overworking here? / Is it safe to leave the Context and Connection Open?
In case it is safe to leave it open I would rather work with 1 static field DSLContext per UtilClass (and only the commented section would be on my methods). I would be opening a connection for each UtilClass since I am encapsulating the methods per table (more or less).
DSLContext is usually not a resource, so you can leave it "open", i.e. you can let the garbage collector collect it for you.
A JDBC Connection, however, is a resource, and as all resources, you should always close it explicitly. The correct way to close resources in Java 7+ is by using the try-with-resources statement:
static void methodA() {
try (Connection con = MySQLConnection.getConexion()) {
DSLContext ctx = DSL.using(con, SQLDialect.MYSQL); //open
/* my logic and jooq queries */
// "ctx" goes out of scope here, and can be garbage-collected
} // "con" will be closed here by the try-with-resources statement
}
More information about the try-with-resources statement can be seen here. Please also notice that the jOOQ tutorial uses the try-with-resources statement when using standalone JDBC connections.
When is DSLContext a resource?
An exception to the above is when you let your DSLContext instance manage the Connection itself, e.g. by passing a connection URL as follows:
try (DSLContext ctx = DSL.using("jdbc:url:something", "username", "password")) {
}
In this case, you will need to close() the DSLContext as shown above

Creating JDBC transaction for second data source with existing connection pool in Glassfish

I have main data source for working with database, which uses some connection pool. Now I want to create a second data source, which would use the same connection pool to perform logging operations in a separate transaction, then main database transaction! As far as I understood from the Glassfish docs if multiple data sources are using the same connection pool, then they share a transaction until connection is not closed (I might be wrong, please correct me).
So, is there a way to start a new transaction, when getting a connection to a data source? By setting TransactionIsolation may be?
Connection is retrieved in the following way:
private synchronized Connection getConnection() {
if (connection == null) {
try {
final Context ctx = new InitialContext();
final DataSource ds = (DataSource) ctx.lookup(getDataSourceLookupAddress());
connection = ds.getConnection();
} catch (final NamingException e) {
errorHandler.error("Datasource JNDI lookup failed: " + dataSourceLookupAddress + "!");
errorHandler.error(e.toString());
} catch (final SQLException e) {
errorHandler.error("Sql connection failed to " + dataSourceLookupAddress + "!");
errorHandler.error(e.toString());
}
}
return connection;
}
I have figured it out. It's necessary to start a new Thread, then a new transaction will be created. See also Writing to database log in the middle of rollback

Reload web server with gwt and c3p0 connection pool?

I have a web application written in gwt, and I'm using a PostgreSQL database in the back end. When I make a new session on the server, I set up c3p0 and get a jdbc connection:
ComboPooledDataSource source = new ComboPooledDataSource();
Properties connectionProps = new Properties();
connectionProps.put("user", "username");
connectionProps.put("password", "password");
source.setProperties(connectionProps);
source.setJdbcUrl("some jdbc url that works");
and when I close my session on the server, I close the ComboPooledDataSource.
However... when I press the yellow "reload web server" button in GWT development mode and refresh my page, I get the following warning, and a bunch of subsequent errors preventing me from obtaining a database connection:
WARNING: A C3P0Registry mbean is already registered. This probably means that an application using c3p0 was undeployed, but not all PooledDataSources were closed prior to undeployment. This may lead to resource leaks over time. Please take care to close all PooledDataSources.
Which I assume means that reloading the web server didn't close the ComboPooledDataSource I made (probably a safe assumption). Is there any way I can get it to do that so I can obtain a connection after reloading the web server?
Closing dataSource generally (not only C3P0) is unadvisable because they should to be used from many applications on your server. If you kill this connection pool other can loose data access. In practice you shoud leave pool management to your container and use only JNDI.
Anyway if you neet to ged rid of the warning in your GWT console use this method in your EventListener contextDestroyer:
public abstract class YourListenerimplements EventListener {
//Probably you initialize your dataSource here. I do it with Guice.
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
...
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
try {
connection = dataSource.getConnection(); //Your dataSource (I obtain it from Guice)
} catch (SQLException ex) {
} finally {
try {
if (connection != null) {
connection.close();
}
if (dataSource != null) {
try {
DataSources.destroy(dataSource);
dataSource = null;
} catch (Exception e) {
}
}
} catch (SQLException sQLException) {
XLog.error(sQLException);
}
}
}
}

Getting Database connection in pure JPA setup

We have a JPA application (using hibernate) and we need to pass a call to a legacy reporting tool that needs a JDBC database connection as a parameter. Is there a simple way to get access to the JDBC connection hibernate has setup?
As per the hibernate docs here,
Connection connection()
Deprecated. (scheduled for removal in 4.x). Replacement depends on need; for doing direct JDBC stuff use
doWork(org.hibernate.jdbc.Work) ...
Use Hibernate Work API instead:
Session session = entityManager.unwrap(Session.class);
session.doWork(new Work() {
#Override
public void execute(Connection connection) throws SQLException {
// do whatever you need to do with the connection
}
});
Where you want to get that connection is unclear. One possibility would be to get it from the underlying Hibernate Session used by the EntityManager. With JPA 1.0, you'll have to do something like this:
Session session = (Session)em.getDelegate();
Connection conn = session.connection();
Note that the getDelegate() is not portable, the result of this method is implementation specific: the above code works in JBoss, for GlassFish you'd have to adapt it - have a look at Be careful while using EntityManager.getDelegate().
In JPA 2.0, things are a bit better and you can do the following:
Connection conn = em.unwrap(Session.class).connection();
If you are running inside a container, you could also perform a lookup on the configured DataSource.
If you are using JAVA EE 5.0, the best way to do this is to use the #Resource annotation to inject the datasource in an attribute of a class (for instance an EJB) to hold the datasource resource (for instance an Oracle datasource) for the legacy reporting tool, this way:
#Resource(mappedName="jdbc:/OracleDefaultDS") DataSource datasource;
Later you can obtain the connection, and pass it to the legacy reporting tool in this way:
Connection conn = dataSource.getConnection();
if you use EclipseLink:
You should be in a JPA transaction to access the Connection
entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
...
entityManager.getTransaction().commit();
Hibernate 4 / 5:
Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> doSomeStuffWith(connection));
Since the code suggested by #Pascal is deprecated as mentioned by #Jacob, I found this another way that works for me.
import org.hibernate.classic.Session;
import org.hibernate.connection.ConnectionProvider;
import org.hibernate.engine.SessionFactoryImplementor;
Session session = (Session) em.getDelegate();
SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
ConnectionProvider cp = sfi.getConnectionProvider();
Connection connection = cp.getConnection();
The word pure doesn't match to the word hibernate.
EclipseLink
Getting a JDBC Connection from an EntityManager
It's somewhat straightforward as described in above link.
Note that the EntityManager must be joined to a Transaction or the unwrap method will return null. (Not a good move at all.)
I'm not sure the responsibility of closing the connection.
// --------------------------------------------------------- EclipseLink
try {
final Connection connection = manager.unwrap(Connection.class);
if (connection != null) { // manage is not in any transaction
return function.apply(connection);
}
} catch (final PersistenceException pe) {
logger.log(FINE, pe, () -> "failed to unwrap as a connection");
}
Hibernate
It should be, basically, done with following codes.
// using vendor specific APIs
final Session session = (Session) manager.unwrap(Session.class);
//return session.doReturningWork<R>(function::apply);
return session.doReturningWork(new ReturningWork<R>() {
#Override public R execute(final Connection connection) {
return function.apply(connection);
}
});
Well, we (at least I) might don't want any vendor-specific dependencies. Proxy comes in rescue.
try {
// See? You shouldn't fire me, ass hole!!!
final Class<?> sessionClass
= Class.forName("org.hibernate.Session");
final Object session = manager.unwrap(sessionClass);
final Class<?> returningWorkClass
= Class.forName("org.hibernate.jdbc.ReturningWork");
final Method executeMethod
= returningWorkClass.getMethod("execute", Connection.class);
final Object workProxy = Proxy.newProxyInstance(
lookup().lookupClass().getClassLoader(),
new Class[]{returningWorkClass},
(proxy, method, args) -> {
if (method.equals(executeMethod)) {
final Connection connection = (Connection) args[0];
return function.apply(connection);
}
return null;
});
final Method doReturningWorkMethod = sessionClass.getMethod(
"doReturningWork", returningWorkClass);
return (R) doReturningWorkMethod.invoke(session, workProxy);
} catch (final ReflectiveOperationException roe) {
logger.log(Level.FINE, roe, () -> "failed to work with hibernate");
}
OpenJPA
Runtime Access to DataSource
OPENJPA-1803 Unwrap EntityManager to Connection
I'm not sure OpenJPA already serves a way using unwrap(Connection.class) but can be done with the way described in one of above links.
It's not clear the responsibility of closing the connection. The document (one of above links) seems saying clearly but I'm not good at English.
try {
final Class<?> k = Class.forName(
"org.apache.openjpa.persistence.OpenJPAEntityManager");
if (k.isInstance(manager)) {
final Method m = k.getMethod("getConnection");
try {
try (Connection c = (Connection) m.invoke(manager)) {
return function.apply(c);
}
} catch (final SQLException sqle) {
logger.log(FINE, sqle, () -> "failed to work with openjpa");
}
}
} catch (final ReflectiveOperationException roe) {
logger.log(Level.FINE, roe, () -> "failed to work with openjpa");
}
Hibernate uses a ConnectionProvider internally to obtain connections. From the hibernate javadoc:
The ConnectionProvider interface is not intended to be exposed to the application. Instead it is used internally by Hibernate to obtain connections.
The more elegant way of solving this would be to create a database connection pool yourself and hand connections to hibernate and your legacy tool from there.
I ran into this problem today and this was the trick I did, which worked for me:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("DAOMANAGER");
EntityManagerem = emf.createEntityManager();
org.hibernate.Session session = ((EntityManagerImpl) em).getSession();
java.sql.Connection connectionObj = session.connection();
Though not the best way but does the job.
Below is the code that worked for me. We use jpa 1.0, Apache openjpa implementation.
import java.sql.Connection;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAPersistence;
public final class MsSqlDaoFactory {
public static final Connection getConnection(final EntityManager entityManager) {
OpenJPAEntityManager openJPAEntityManager = OpenJPAPersistence.cast(entityManager);
Connection connection = (Connection) openJPAEntityManager.getConnection();
return connection;
}
}
I'm using a old version of Hibernate (3.3.0) with a newest version of OpenEJB (4.6.0). My solution was:
EntityManagerImpl entityManager = (EntityManagerImpl)em.getDelegate();
Session session = entityManager.getSession();
Connection connection = session.connection();
Statement statement = null;
try {
statement = connection.createStatement();
statement.execute(sql);
connection.commit();
} catch (SQLException e) {
throw new RuntimeException(e);
}
I had an error after that:
Commit can not be set while enrolled in a transaction
Because this code above was inside a EJB Controller (you can't commit inside a transaction). I annotated the method with #TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED) and the problem was gone.
Here is a code snippet that works with Hibernate 4 based on Dominik's answer
Connection getConnection() {
Session session = entityManager.unwrap(Session.class);
MyWork myWork = new MyWork();
session.doWork(myWork);
return myWork.getConnection();
}
private static class MyWork implements Work {
Connection conn;
#Override
public void execute(Connection arg0) throws SQLException {
this.conn = arg0;
}
Connection getConnection() {
return conn;
}
}
I am a little bit new to Spring Boot, I have needing the Connection object to send it to Jasperreport also, after trying the different answers in this post, this was only useful for me and, I hope it helps someone who is stuck at this point.
#Repository
public class GenericRepository {
private final EntityManager entityManager;
#Autowired
public GenericRepository(EntityManager entityManager, DataSource dataSource) {
this.entityManager = entityManager;
}
public Connection getConnection() throws SQLException {
Map<String, Object> properties = entityManager.getEntityManagerFactory().getProperties();
HikariDataSource dataSource = (HikariDataSource) properties.get("javax.persistence.nonJtaDataSource");
return dataSource.getConnection();
}
}

Java Threads and MySQL

I have a threaded chat server application which requires MySQL authencation.
Is the best way to have 1 class create the MySQL connection, keep that connection open and let every thread use that connection but use own Query handler?
Or is it better to have all threads make a seperate connection to MySQL to authencate?
Or is it better to let 1 class handle the queries AND connections?
We are looking at a chatserver that should be able to handle upto 10.000 connections/users.
I am now using c3p0, and I created this:
public static void main(String[] args) throws PropertyVetoException
{
ComboPooledDataSource pool = new ComboPooledDataSource();
pool.setDriverClass("com.mysql.jdbc.Driver");
pool.setJdbcUrl("jdbc:mysql://localhost:3306/db");
pool.setUser("root");
pool.setPassword("pw");
pool.setMaxPoolSize(100);
pool.setMinPoolSize(10);
Database database = new Database(pool);
try
{
ResultSet rs = database.query("SELECT * FROM `users`");
while (rs.next()) {
System.out.println(rs.getString("userid"));
System.out.println(rs.getString("username"));
}
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
finally
{
database.close();
}
}
public class Database {
ComboPooledDataSource pool;
Connection conn;
ResultSet rs = null;
Statement st = null;
public Database (ComboPooledDataSource p_pool)
{
pool = p_pool;
}
public ResultSet query (String _query)
{
try {
conn = pool.getConnection();
st = conn.createStatement();
rs = st.executeQuery(_query);
} catch (SQLException e) {
e.printStackTrace();
} finally {
}
return rs;
}
public void close ()
{
try {
st.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Would this be thread safe?
c3p0 connection pool is a robust solution. You can also check dbcp but c3p0 shows better performance, supports auto-reconnection and some other features.
Have you looked at connection pooling ? Check out (for example) Apache DBCP or C3P0.
Briefly, connection pooling means that a pool of authenticated connections are used, and free connections are passed to you on request. You can configure the number of connections as appropriate. When you close a connection, it's actually returned to the pool and made available for another client. It makes life relatively easy in your scenario, since the pool looks after the authentication and connection management.
You should not have just one connection. It's not a thread-safe class. The idea is to get a connection, use it, and close it in the narrowest scope possible.
Yes, you'll need a pool of them. Every Java EE app server will have a JNDI pooling mechanism for you. I wouldn't recommend one class for all queries, either. Your chat ap
Your chat app ought to have a few sensible objects in its domain model. I'd create data access objects for them as appropriate. Keep the queries related to a particular domain model object in its DAO.
is the info in this thread up-to-date? Googling brings up a lot of different things, as well as this - http://dev.mysql.com/tech-resources/articles/connection_pooling_with_connectorj.html

Categories