问题
I'm trying to wrap my ahead around some strange errors, where code that seemingly should run as one transaction does not. I'll try to get all the relevant parts down, but it's quite a lot so.
The project contains both Spring and EJB, so I'm not really sure if one of them is actually used here, or both.
The Spring configuration contains this:
<jee:jndi-lookup id="platformTransactionManager" jndi-name="java:appserver/TransactionManager" resource-ref="false"
expected-type="javax.transaction.TransactionManager" lookup-on-startup="false"/>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager" lazy-init="true">
<constructor-arg ref="platformTransactionManager"/>
<property name="autodetectUserTransaction" value="false"/>
<property name="allowCustomIsolationLevels" value="true"/>
</bean>
<tx:annotation-driven/>
Then, I have the following Java-code (a bit simplified, but should contain all relevant details):
@Stateless
@ApplicationException(rollback = true)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Local(MyLocal.class)
@Remote(MyRemote.class)
@EJB(beanInterface = MyLocal.class, name = "java:app/MyEJB", beanName = "MyEJB")
public class MyEJB {
public void insertSomething(final Something something) {
final com.microsoft.sqlserver.jdbc.SQLServerXADataSource dataSource;
final SomethingElse somethingElse = something.getSomethingElse();
//insert 1
try {
final String sql = convertToInsertSql(somethingElse);
dataSource = //gets the datasource from Glassfish via JNDI
final Connection conn = dataSource.getConnection();
final Statement stmt = conn.createStatement();
stmt.execute(sql);
//this is actually wrapped in a method that returns the id of created row
//I have removed this for brevity, but assume that you get that back
} finally {
conn.close();
}
something.getSomethingElse().setId(/* id from the result above */)
// insert 2
try {
final String sql = convertToInsertSql(something);
dataSource = //gets the datasource from Glassfish via JNDI
final Connection conn = dataSource.getConnection();
final Statement stmt = conn.createStatement();
stmt.execute(sql);
} finally {
conn.close();
}
}
}
At last, the class that invokes the method above (without boring SOAP-stuff):
public class MyService extends SpringBeanAutowiringSupport {
@Inject
private MyLocal myLocal;
public void createSomething(/*stuff*/) {
/* more stuff */
myLocal.insertSomething(something);
}
}
I have several questions here:
- What (if any) transactions will be created?
- Is the transactionManager defined with Spring in play here, or just the glassfish jndi one?
- Assuming a transaction across the method insertSomething:
- What will happen to the query when the connection is closed mid-transaction (insert 1)?
- What will happen if an error appears after the connection is closed (after insert 1)?
- Is there a possibility of insert 2 being commited to the database, while insert 1 is not? If so, how? (this is the error that I'm actually debugging)
- What are the consequences of the use of
getConnection()
of theSQLServerXADataSource
?- Will we have XA (I would assume you had to use one of the XA-related methods for getting a connection)?
- Will we have connection pooling (
getConnection()
invokes an internal method with pooling variable set to null)?
If you think this question is messy, you should see the project I based it on ;)
来源:https://stackoverflow.com/questions/59376413/what-are-the-consequences-of-opening-closing-connections-within-a-transaction