Spring事务日志记录已回滚但未回滚

时间:2017-06-19 22:00:16

标签: java spring spring-transactions

这些是我的课程和配置,

ServiceImpl.java

@Override
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public InsertUpdateSuccessBean insertNewSiteEntry(SiteEntry newSiteBean) throws SQLException {
    dao.insert1();
    dao.insert2();
    except();
    return new InsertUpdateSuccessBean(true,LoggerConstants.NEW_SITE_ENTRY_SUCCESS);
}
private void except()throws SQLException{
throw new SQLException();
}

DAOImpl.java

@Repository
public class DAOImpl implements DAO 
{
    @Autowired
    private DataSourceTransactionManager transManager;
    @Autowired
    private CommonDAOUtils commonUtils;
    private static final Logger logger = Logger.getLogger(HunterDAOImpl.class) ;
    @Override
    public Integer insert1() throws SQLException { 
    Integer insertNumRows = 0;
    Connection connectionObject = transManager.getDataSource().getConnection();
    PreparedStatement psObject = connectionObject.prepareStatement(
 SQLQuery );
    insertNumRows = psObject.executeUpdate();
    commonUtils.closer(null,psObject,connectionObject);
        // Function to close open connection resultsets statement objects
    return insertNumRows;
}

     @Override
    public Integer insert2() throws SQLException {
    Integer insertNumRows = 0;
    Connection connectionObject = transManager.getDataSource().getConnection();
    PreparedStatement psObject = connectionObject.prepareStatement(
 SQLQuery );
    insertNumRows = psObject.executeUpdate();
    commonUtils.closer(null,psObject,connectionObject);
        // Function to close open connection resultsets statement objects
    return insertNumRows;
}
}

AppConfig.java

import com.interceptors.AppInterceptor;
import com.utils.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Component
@Configuration
@EnableWebMvc
@Configurable
@ComponentScan(basePackages = {Constants.BASE_PACKAGE})
@EnableAspectJAutoProxy(proxyTargetClass = true)
@PropertySource(Constants.DB_PROPERTIES_PATH)
@EnableTransactionManagement
public class AppConfig extends WebMvcConfigurerAdapter implements EnvironmentAware{

    @Autowired
    Environment environmentObject;

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
        PropertySourcesPlaceholderConfigurer placeHolder =new PropertySourcesPlaceholderConfigurer();
        placeHolder.setLocation(new ClassPathResource(Constants.PROP_FILE_NAME));
        return placeHolder;
    }

    @Bean
    public InternalResourceViewResolver viewResolver(){
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        internalResourceViewResolver.setPrefix(Constants.ROOT_PATH);
        internalResourceViewResolver.setSuffix(Constants.JSP_DOT_EXTENSION);
        return internalResourceViewResolver;
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public DriverManagerDataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(environmentObject.getProperty(Constants.JDBC_DRIVERCLASS_NAME_PROP_FILE));
        driverManagerDataSource.setUrl(environmentObject.getProperty(Constants.JDBC_URL_PROP_FILE));
        driverManagerDataSource.setUsername(environmentObject.getProperty(Constants.JDBC_USERNAME_PROP_FILE));
        driverManagerDataSource.setPassword(new String(Constants.PASSWORD));
        return driverManagerDataSource;
    }

    @Bean
    public AutowiredAnnotationBeanPostProcessor postProcessorBean(){
        return new AutowiredAnnotationBeanPostProcessor();
    }



    private ClientHttpRequestFactory getClientHttpRequestFactory() {
        int timeout = 5000;
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setConnectTimeout(timeout);
        return clientHttpRequestFactory;
    }

    @Bean
    public DataSourceTransactionManager transactionManager(){
        final DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
        transactionManager.setRollbackOnCommitFailure(true);
        return transactionManager;
    }
}

我也对我的项目提出了建议:

@Aspect
@Component
public class AroundAdvice
{
    private static final Logger logger = Logger.getLogger(AroundAdvice.class) ;
    // Add pointcuts here - package names here for around advice
    @Around("execution(* com.beans.*.*(..)) || " +
            "execution(* com.config.*.*(..)) || " +
            "execution(* com.controller.*.*(..)) || " +
            "execution(* com.dao.*.*(..)) || " +
            "execution(* com.service.*.*(..)) || " +
            "execution(* com.utils.*.*(..)) || "+
            "execution(* com.interceptors.*.*(..))")
    public Object aroundAdviceMethod(ProceedingJoinPoint proceedingObject)throws Throwable{
        MethodSignature methodSignObject = (MethodSignature) proceedingObject.getSignature();
        logger.debug(Constants.EXECUTING_METH_STR + methodSignObject.getMethod());
        Object value = null;
        try {
            value = proceedingObject.proceed();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(Constants.EXCEPTION_ASPECT_STR+methodSignObject.getMethod());
            logger.error(Constants.EXCEPTION_MESSAGE,e);
            throw e;
        }
        logger.debug(Constants.RETURN_STR+value);
        return value;
    }
}

在执行此流时,插入成功,但是当抛出异常时,它不会回滚。但是,我的记录器读取回滚初始化并按如下方式完成,

14:11:51 DEBUG DataSourceTransactionManager:851 - Initiating transaction rollback
14:11:51 DEBUG DataSourceTransactionManager:325 - Rolling back JDBC transaction on Connection [org.postgresql.jdbc4.Jdbc4Connection@3b467b21]
14:11:51 DEBUG DataSourceTransactionManager:368 - Releasing JDBC Connection [org.postgresql.jdbc4.Jdbc4Connection@3b467b21] after transaction

如果我错过了什么,请告诉我

1 个答案:

答案 0 :(得分:1)

问题是你的道歉。您自己打开连接,因此绕过所有事务管理。你的dao是复杂的只需使用JdbcTemplate而不是你当前的代码。

@Repository
public class DAOImpl implements DAO {
    private static final Logger logger = Logger.getLogger(HunterDAOImpl.class) ;

    private final JdbcTemplate jdbc;

    public DAOImpl(DataSource dataSource) {
        this.jdbc = new JdbcTemplate(dataSource);
    }

    @Override
    public Integer insert1() throws SQLException { 
        return jdbc.update(SQLQuery);
    }

     @Override
    public Integer insert2() throws SQLException {
        return jdbc.update(SQLQuery);
    }

}

这与您的代码完全相同,但主要区别在于它将使用启动事务时打开的Connection。您的示例使用3个单独的连接,因此使用3个单独的事务而不是1个单个事务。