2015-07-06 3 views
2

Я разрабатываю небольшое приложение на Java с использованием Spring framework. В рамках этого проекта я разработал инструмент командной строки в этом весеннем проекте, который читается в CSV-файле и вставляет его в базу данных MySQL.Spring - использование управления аннотационными транзакциями в инструменте командной строки

Я хотел бы использовать собственное управление сделками Soring для этой цели, и я нахожу аннотационный метод, используя @Transactional привлекательный. Проблема в том, что функция с этой аннотацией не откатывается, даже если генерируется исключение.

Это небольшая часть моего кода, я считаю, имеет отношение к этому вопросу:

public static void main(String[] args) throws Exception { 

    //some variables and stuff here 

    //getting application context 
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class); 
    JdbcOperations jdbcOperations = applicationContext.getBean("jdbcOperations", JdbcOperations.class); 
    UserDaoImpl userDaoImpl = applicationContext.getBean("userDao", UserDaoImpl.class); 
    DBDaoImpl DBDaoImpl = applicationContext.getBean("dbDao", DBDaoImpl.class); 

    UserDetailImporterTool importerTool = new UserDetailImporterTool(jdbcOperations, DBDaoImpl, userDaoImpl); 

    //this functions calls a DAO 
    importerTool.execute(users, userFollowingMapCSV, batchSize); 
} 

Это функция Execute(), который вызывается формой указанных выше main():

public int execute(List<User> users, String userFollowingMapCSV, int batchSize) throws Exception{ 
    // stuff here 

    int numSuccessfulInsertions = userDaoImpl.insert(users, jdbcOperations, batchSize); 

    // stuff here 
} 

Это функция insert(), вызываемая от execute(), функция, указанная выше:

@Override 
public int insert(@Nonnull List<User> user, 
        @Nonnull JdbcOperations jdbcOperations, 
        int batchSize) throws Exception 
{ 
    //stuff here 

     try { 
      insertBatch(jdbcOperations, 
        userArgsList, 
        userDetailArgsList, 
        officialDetailArgsList, 
        residentialDetailArgsList 
      ); 
     } catch (Exception e) { 
      LOGGER.warning("ERROR"); 
     } 
    } 
    // stuff here 
} 

И, наконец, это insertBatch() функция в DAO, на которой управление транзакциями применяется на:

@Transactional("dataSourceTransactionManager") 
private void insertBatch(JdbcOperations jdbcOperations, 
         List<Object[]> userArgsList, 
         List<Object[]> userDetailArgsList, 
         List<Object[]> officialDetailArgsList, 
         List<Object[]> residentialDetailArgsList 
) throws Exception 
{ 
    try { 
     jdbcOperations.batchUpdate(userSql, userArgsList); 
     jdbcOperations.batchUpdate(userDetailSql, userDetailArgsList); 
     jdbcOperations.batchUpdate(officialDetailSql, officialDetailArgsList); 
     jdbcOperations.batchUpdate(residentailDetailSql, residentialDetailArgsList); 
    } catch (Exception e) { 
     LOGGER.warning(debugMessageIndicator + " Batch failed to insert. Error : " + e.getMessage()); 
     throw new Exception(); 
    } 


} 

И, наконец, (я обещаю, что это последний фрагмент: P) это мой конфигурационный файл боб:

@EnableTransactionManagement 
@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass = true) 
@PropertySource("classpath:application.properties") 
public class BeanConfig { 

private static final String VALIDATION_QUERY = "SELECT 1"; 

@Autowired 
private Environment env; 

@Bean 
public BasicDataSource dataSource() { 
    String driverClassName = env.getProperty("db.driverClassName"); 
    String jdbcUrl = env.getProperty("db.jdbcUrl"); 
    String username = env.getProperty("db.username"); 
    String password = env.getProperty("db.password"); 

    BasicDataSource basicDataSource = new BasicDataSource(); 
    basicDataSource.setDriverClassName(driverClassName); 
    basicDataSource.setUrl(jdbcUrl); 
    basicDataSource.setUsername(username); 
    basicDataSource.setPassword(password); 

    basicDataSource.setValidationQuery(VALIDATION_QUERY); 
    basicDataSource.setValidationQueryTimeout(1); 
    basicDataSource.setTestOnBorrow(true); 
    basicDataSource.setTestWhileIdle(true); 

    return basicDataSource; 
} 

@Bean 
public JdbcOperations jdbcOperations() { 
    BasicDataSource dataSource = dataSource(); 
    return new JdbcTemplate(dataSource); 
} 

@Bean 
public UserDAO userDao() { 
    return new UserDaoImpl(); 
} 

@Bean 
public DBDao dbDao() { 
    return new DBDaoImpl(); 
} 

@Bean 
public PlatformTransactionManager transactionManager(){ 
    BasicDataSource dataSource = dataSource(); 
    return new DataSourceTransactionManager(dataSource); 
} 

}

Я считаю, что все это требовалось, чтобы увидеть полный поток управления. Как вы можете видеть, несмотря на то, что я удаляю исключение, откат не выполняется. Мне сказал кто-то, что я не могу использовать управление аннотационными транзакциями, если я не развожу WAR-файл проекта на Tomcat. Прямо сейчас я запускаю это из командной строки через maven.

Это действительно так, что я не могу использовать @Transactional без развертывания? Существуют ли какие-либо ошибки, препятствующие выполнению формы отката?

Я попытался установить auto commit на false в DataSource bean, но без успеха. Любые указатели будут полезны.

+0

с использованием любой аннотации для этого конкретного класса -> UserDetailImporterTool ?? это должно быть в области @Transactional. Если вы не аннотировали этот класс, добавьте @Transactional (rollbackFor = Exception.class) в этот класс. Надеюсь, что работает – ManinGreen

ответ

0
  1. Если я вижу, у вас есть проверенное исключение. Но в этом случае Spring Транзакция не отменяет транзакцию по умолчанию. По умолчанию отменены исключения только . Спринг документация говорит:

    Хотя поведение EJB по умолчанию для EJB контейнер для автоматически откатить транзакцию на исключение системы (обычно исключение во время выполнения), EJB CMT не выполняет откат транзакции автоматически исключение приложения (то есть исключение , отличное от java.rmi.RemoteException). В то время как поведение по умолчанию Spring для декларативного управления транзакциями следует за EJB (возврат выполняется автоматически только по незафиксированным исключениям), это полезно для настройки этого параметра .

    Вы должны определить его выше своего класса:

    @Transactional(rollbackFor=Exception.class) class YourClassName {}

    Или вы можете указать конкретное проверяемое исключение.

  2. Можно использовать весеннюю транзакцию (@Transactional и другие аннотации) без сервлетов контейнеров, таких как Tomcat. Это совершенно разные вещи.

UPDATE: Кроме того, необходимо определить TransactionManager в классе конфигурации, как показано here:

@Bean 
    public PlatformTransactionManager txManager() { 
     return new DataSourceTransactionManager(dataSource()); 
    } 

UPDATE 2: Вам не нужно загружать все бобы в вашем методе main() вручную , Лучший способ указать отношения между вашими бобами. Только основная служба должна загружаться вручную. И контейнер Spring сделает эту работу для вас. Также транзакция будет работать правильно. Как показано here.

+0

Я попытался добавить, что прямо над объявлением для класса JdbcUserDao (класс, содержащий все операции с БД), но это не сработало. Я также попытался добавить его поверх функции execute, но это тоже не сработало. –

+0

Как вы думаете, вы могли бы предоставить действительно маленький демо-код для этого? Это было бы полезно –

+0

Я не вижу определения transactionManager в вашем классе конфигурации 'BeanConfig'. Вы должны сделать, как показано выше. –

0

используя любую аннотацию для этого конкретного класса ->UserDetailImporterTool ?? это должно быть в области @Transactional. Если не аннотированный этот класс поставьте

@Transactional (rollbackFor = Exception.class)

выше этого класса, а также. Надеюсь, что это работает!

+0

К сожалению, это не сработало –

+0

Должен ли я упоминать об этом в конфигурации bean или в исходном файле класса? –

+0

где именно вы получаете исключение? – ManinGreen

Смежные вопросы