This content has been marked as final.
Show 1 reply
-
1. Re: Single UPDATE instead of SELECT, then UPDATE
lauri Jun 2, 2006 2:31 PM (in response to lauri)The problem has been solved.
I'd like to share the story.
The question was going from obivious lack of J2EE and JBoss experience and understanding.
I was absolutely sure that dataSource.getConnection() returns free connection and this free connection means new transaction.
I've had tried to use same datasource for cmp beans and session beans. Lets say it is registered as java:jdbc/cmp in global evinonent (possibly other depoyments use java:DefaultDS or java:MySqlDS).
I've placed a ref link to it for my Session bean Cashier. In xdoclet attributes it looks like:@ejb.resource-ref res-ref-name="dataSource" ref-type="javax.sql.DataSource" jndi-name="java:jdbc/cmp" res-auth="Container" @jboss.resource-ref res-ref-name="dataSource" jndi-name="java:jdbc/cmp"
Cashier session bean has a private field of javax.sql.DataSource type dataSource. It is being initialized in ejbCreate()public void ejbCreate() throws CreateException { try { InitialContext ctx = new InitialContext(); this.dataSource = (DataSource) ctx.lookup("java:comp/env/dataSource"); //.... } catch (NamingException nEx) { throw new RuntimeException(nEx); } }
Now dataSource field is usable.
So deposit() method from example above has changed topublic void deposit(Integer customerId, int value) throws RemoteException { Connection conn = null; try { conn = this.dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement("UPDATE customer SET credits=credits+? WHERE id =?"); stmt.setInt(1, value); stmt.setObject(2, customerId); stmt.executeUpdate(); } catch .... { ///.... bla bla. catch some common exceptions } finally { if(conn != null) { try { conn.close(); } catch (SQLException sqlEx) { // log error } } } }
That is really simple and was hard for me to believe.
Queries generated inside new deposit method come inside transaction which is managed by container! (I've verified it from mysql query logs). It is forbidden to use conn.commit(), conn.rollback() and conn.setAutoComint(...) methods, an exception will be thrown and whole transaction will be rolled back.
Similar solution has been applied to many methods for local edition of the Cashier bean.
Total application has been stress tested with REPETABLE_READ isolation level for mysql. Works perfectly.
At least one drawback indeed exist, now sql code moved to java code (or deployment descriptors). It is not very beautiful to my humble opinion.
P.S. Next question of curiosity. Will other containers behave in the same way? I hope it will never come to find an answer myself :).