I try to write a transaction manager using JDBC in Spring.
my app-servlet.xml
<!-- JDBC Config -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<!-- dataSource TransactionManager -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="UserDAOImpl" class="com.project.dao.impl.UserDAOImpl">
<property name="transactionManager" ref="transactionManager"/>
</bean>
my UserDAOImpl.java
public class UserDAOImpl implements UserDAO {
//transaction manager
private DataSourceTransactionManager transactionManager;
private JdbcTemplate jdbcTemplate;
public UserDAOImpl() {
super();
DataSource dataSource = transactionManager.getDataSource();
jdbcTemplate = new JdbcTemplate(dataSource);
}
public void setTransactionManager(DataSourceTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
....
}
Even though I have transactionManager
Bean in my app-servlet, UserDAOImpl
won't be instatiated because transactionManager
is null
. Probably I miss some point but couldn't find out what is wrong.
It loops through the list of people and, for each person, inserts that person into the BOOKINGS table by using the JdbcTemplate . This method is tagged with @Transactional , meaning that any failure causes the entire operation to roll back to its previous state and to re-throw the original exception.
Make sure that your Spring Configuration is annotated with the @EnableTransactionManagement annotation (In Spring Boot this will be done automatically for you). Make sure you specify a transaction manager in your Spring Configuration (this you need to do anyway).
The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.
You should use constructor injection for your transaction manager. Spring is going to call the constructor before it can inject the transactionManager property.
public UserDAOImpl()
{
/* Transaction Manager NOT set yet */
DataSource dataSource = transactionManager.getDataSource();
}
Change it to use constructor injection
public UserDAOImpl(TransactionManager transactionManager) ...
Then configuration
<bean id="UserDAOImpl" class="com.project.dao.impl.UserDAOImpl">
<constructor-arg ref="transactionManager"/>
</bean>
If you are using spring with annotations, this should work
@Repository
public class UserDAOImpl implements UserDAO{
@Autowired
private DataSourceTransactionManager transactionManager;
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
and you can do away with this line in the configuration
<bean id="UserDAOImpl" class="com.project.dao.impl.UserDAOImpl">
<property name="transactionManager" ref="transactionManager"/>
</bean>
instead do a component scan:
<!-- Scans within the base package of the application for @Components to configure as beans -->
<context:component-scan base-package="${your package}" />
You can refer more on this in the documentation. If you aren't using annotations change the release version in the URL of the given link to the one you are using. That has enough enough examples to do the same without annotations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With