问题描述
对于下面代码中的插入操作,插入查询成功执行但更新查询抛出异常。
预期结果:如果出现任何异常,即使插入查询成功执行,该事务也应该回滚,并且不会因为更新查询抛出异常而发生更新。
实际结果:插入查询的事务自动提交,更新查询没有任何反应(因为这里抛出异常)
请帮助我达到预期的结果。
这是我的代码
import javax.servlet.http.HttpSession;
import org.springframework.jdbc.core.JdbcTemplate;
@Component("productDao")
public class ProductDaoImpl implements ProductDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
HttpSession httpSession;
@Override
public boolean manageDBOperation(String operation,Data dataFromUser) {
UserData userSessionData = (UserData) httpSession.getAttribute("userDetailsData");
if(null != userSessionData) {
int status = 0;
int status1 = 0;
switch (operation) {
case "INSERT":
try {
try {
status1 = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(MysqLQueries.INSERT_QUERY);
ps.setString(1,var1);
ps.setString(2,var2);
ps.setString(3,var3);
return ps;
});
// return status1 != 0;
} catch (Exception e) {
logger.error("Error in inserting ==== ",e);
e.printstacktrace();
}
if (status1 != 0) {
try {
status = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(MysqLQueries.UPDATE_QUERY);
ps.setString(1,var1);
ps.setString(2,var2);
ps.setString(3,var3);
return ps;
});
return status != 0;
} catch (Exception e) {
logger.error("Error in updating ==== ",e);
e.printstacktrace();
}
}
} catch (Exception e) {
logger.error("Error in " + operation + " operation ==== ",e);
e.printstacktrace();
}
break;
case "UPDATE":
try {
try {
status1 = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(MysqLQueries.UPDATE_QUERY1);
ps.setString(1,var3);
return ps;
});
// return status1 != 0;
} catch (Exception e) {
logger.error("Error in updating ==== ",e);
e.printstacktrace();
}
if (status1 != 0) {
try {
status = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(MysqLQueries.UPDATE_QUERY2);
ps.setString(1,var3);
return ps;
});
return status != 0;
} catch (Exception e) {
logger.error("Error in ==== ",e);
e.printstacktrace();
}
break;
case "DELETE":
try {
try {
status1 = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(MysqLQueries.DELETE_QUERY);
ps.setString(1,var3);
return ps;
});
// return status1 != 0;
} catch (Exception e) {
logger.error("Error in deleting ==== ",e);
e.printstacktrace();
}
if (status1 != 0) {
try {
status = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement( MysqLQueries.UPDATE_QUERY);
ps.setString(1,var3);
return ps;
});
return status != 0;
} catch (Exception e) {
logger.error("Error in updating ==== ",e);
e.printstacktrace();
}
break;
default:
logger.warn("No Matched Operation found");
}
}
return false;
}
}
解决方法
创建一个 Configuration
类,如下所示
@Configuration
@ComponentScan("YOUR_BASE_PATH")
@EnableTransactionManagement
public class MyConfig{
@Bean(name = "MyDataSource")
@Primary
public DataSource getMyDataSource() {
//return your data source by reading userName,password,url
return dataSource;
}
//By using above data source create a Entity Manager factory like below
@Primary
@Bean(name = "myEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean yccEntityManagerFactory1(@Qualifier("MyDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf = initializeEntityManagerFactory(dataSource);
emf.setPackagesToScan("YOUR_PACKAGE_TO_SCAN");
return emf;
}
//By using entity Manager Factory cretae a transactionManager like below
@Bean(name = "myTransactionManager")
public PlatformTransactionManager seedTransactionManager(@Qualifier("myEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
private LocalContainerEntityManagerFactoryBean initializeEntityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource);
emf.setPersistenceProviderClass(org.hibernate.jpa.HibernatePersistenceProvider.class);
final Properties properties = new Properties();
emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
properties.put("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");
emf.setJpaProperties(properties);
return emf;
}
现在我们必须通过传递 MyTransaction
作为值来创建 myTransactionManager
接口
@Retention(RUNTIME)
@Target({ TYPE,METHOD })
@Transactional(value="myTransactionManager",rollbackFor={Exception.class})
public @interface MyTransaction{
}
用法:
现在您可以在要回滚的任何类级别上使用 @MyTransaction
@MyTransaction
public class MyService{
}
或
@Transactional("myTransactionManager")
public class MyService{
}