I am trying to work on a small program where I can connect to multiple databases using Spring and trying to use Spring transactions by deploying my web-application on weblogic server. The problem is that the transaction management is not working properly. I am trying to insert records in 2 databases, the first one inserts without throwing any exceptions, where as the second insert query is written such that it throws an exception. Ideally in this situation the transaction should rollback but the first transaction is committed without any issues.
Here is my spring-config.xml file
<context:component-scan base-package="com.examples" />
<!-- Database1 -->
<bean id="db1DataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb1" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<!-- Database2 -->
<bean id="db2DataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb2" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix" value=".jsp" />
</bean>
This is my controller:
@Controller
public class EmployeeController {
@Autowired
private CommonEmployeeService commonService;
@RequestMapping(value = "/employee", method = GET)
public String showPersonListForGivenAge(
@RequestParam(value = "id") int id,
@RequestParam(value = "name") String name,
@RequestParam(value = "email") String email,
Map<String, Object> model) {
Employee e = new Employee(id,name);
EmployeeDetails details = new EmployeeDetails(id,email);
commonService.insert(e, details);
return "welcome";
}
}
This is my common service:
@Service
public class CommonEmployeeService {
@Autowired
EmployeeDetailsService detailsService;
@Autowired
EmployeeService service;
@Transactional
public boolean insert(Employee e, EmployeeDetails details) {
service.insert(e);
detailsService.insert(details);
return true;
}
}
These are my other services:
EmployeeService.java
@Service
public class EmployeeService {
@Autowired
EmployeeDao dao;
//@Transactional(propagation=Propagation.REQUIRED)
public boolean insert(Employee e) {
return dao.insert(e);
}
}
EmployeeDetailsService.java -- The DAO in this service throws NullPointerException
@Service
public class EmployeeDetailsService {
@Autowired
EmployeeDetailsDao dao;
//@Transactional(propagation=Propagation.REQUIRED)
public boolean insert(EmployeeDetails e) {
return dao.insert(e);
}
}
Update: Adding Dao Classes:
EmployeeDao.java:
@Repository
public class EmployeeDao {
JdbcTemplate template;
@Resource(name = "db1DataSource")
public void setDataSource(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
public boolean insert(Employee e) {
int cnt = template.update("insert into Employee values(?,?)",
e.getId(), e.getName());
if (cnt > 0) {
return true;
}
return false;
}
}
EmployeeDetailsDao.java
@Repository
public class EmployeeDetailsDao {
JdbcTemplate template;
@Resource(name = "db2DataSource")
public void setDataSource(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
public boolean insert(EmployeeDetails e) {
if(e != null){
throw new NullPointerException();
}
int cnt = template.update("insert into EmployeeDetails values(?,?)",
e.getId(), e.getEmail());
if (cnt > 0) {
return true;
}
return false;
}
}
Try adding below in spring-config.xml
:
<context:component-scan base-package=“your.packagename.contatining.EmployeeDetailsDao” />
<mvc:annotation-driven />
and changing @Transactional
in your CommonEmployeeService
with @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
as below
@Service
public class CommonEmployeeService {
@Autowired
EmployeeDetailsService detailsService;
@Autowired
EmployeeService service;
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
public boolean insert(Employee e, EmployeeDetails details) {
service.insert(e);
detailsService.insert(details);
return true;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.