Метод сохранения SpringData не работал без каких-либо исключений. База на JTA атомикос и EclipseLink - PullRequest
0 голосов
/ 13 января 2019

У меня уже есть setUp SpringBoot + atomikos + SpringData (Hibernate) + JTA, и это работает, но после того, как я заменил hibernate на EclipseLink, проект не может вставить ни одну запись, там не было никаких исключений и никаких журналов SQL.

вот соответствующий код

Исходник-

связанная зависимость

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.jpa</artifactId>
        <version>2.7.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.2</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.54</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.7.0</version>
    </dependency>

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.7.0</version>
    </dependency>

    <dependency>
        <groupId>org.jmockit</groupId>
        <artifactId>jmockit</artifactId>
        <version>1.33</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jta-atomikos</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp -->
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-dbcp</artifactId>
        <version>8.5.4</version>
    </dependency>


</dependencies>

Слушайте, это MainConfig

@Configuration
public class MainConfig {
   @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {
    UserTransactionImp userTransactionImp = new UserTransactionImp();
    userTransactionImp.setTransactionTimeout(10000);
    return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager", initMethod = "init",   destroyMethod = "close")
     public TransactionManager atomikosTransactionManager() throws Throwable {
    UserTransactionManager userTransactionManager = new UserTransactionManager();
    userTransactionManager.setForceShutdown(true);
    return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({ "userTransaction", "atomikosTransactionManager" })
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransaction userTransaction = userTransaction();
        TransactionManager atomikosTransactionManager = atomikosTransactionManager();
        JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, atomikosTransactionManager);
        jtaTransactionManager.setAllowCustomIsolationLevels(true);
        return jtaTransactionManager;
     }
}

DS1 Config

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@EnableJpaRepositories(basePackages = "com.evan.jta.repository.ds1", entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
public class JpaConfigDs1{
    @Bean(name = "dataSource", initMethod = "init", destroyMethod = "close")
    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.jta-user")
    public DataSource dataSource() {
        System.out.println("jta-user dataSource init");
        return new AtomikosDataSourceBean();
    }

    @Bean(name = "jpaVendorAdapter")
    public JpaVendorAdapter jpaVendorAdapter() {
        System.out.println("jpaVendorAdapter init");
        EclipseLinkJpaVendorAdapter adapter = new EclipseLinkJpaVendorAdapter();
        adapter.setShowSql(true);
        adapter.setDatabase(Database.MYSQL); adapter.setDatabasePlatform("org.eclipse.persistence.platform.database.MySQLPlatform");
        adapter.setGenerateDdl(true);
        return adapter;
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
       System.out.println("entityManagerFactory init");
        LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
        entityManager.setJpaVendorAdapter(jpaVendorAdapter());
        // entity package
        entityManager.setPackagesToScan("com.evan.jta.model.ds1");
        entityManager.setJtaDataSource(dataSource());
        Properties properties = new Properties();
        properties.put("eclipselink.weaving", "false");
        entityManager.setJpaProperties(properties);
        entityManager.setPersistenceUnitName("entityManagerFactory_user");
        return entityManager;

    }

}

DS2 Config

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@EnableJpaRepositories(basePackages = "com.evan.jta.repository.ds2", entityManagerFactoryRef = "entityManagerFactory2", transactionManagerRef = "transactionManager")
public class JpaConfigDs2{
    @Bean(name = "dataSource2", initMethod = "init", destroyMethod = "close")
    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.jta-product")
    public DataSource dataSource() {
        System.out.println("jta-product dataSource init");
        return new AtomikosDataSourceBean();
    }
    @Bean(name = "jpaVendorAdapter2")
    public JpaVendorAdapter jpaVendorAdapter() {
        System.out.println("jpaVendorAdapter init");
        EclipseLinkJpaVendorAdapter adapter = new EclipseLinkJpaVendorAdapter();
        adapter.setShowSql(true);
        adapter.setDatabase(Database.MYSQL);            adapter.setDatabasePlatform("org.eclipse.persistence.platform.database.MySQLPlatform");
        adapter.setGenerateDdl(true);
        return adapter;
    }

    @Bean(name = "entityManagerFactory2")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
       System.out.println("entityManagerFactory init");
        LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
        entityManager.setJpaVendorAdapter(jpaVendorAdapter());
        // entity package
        entityManager.setPackagesToScan("com.evan.jta.model.ds2");
        entityManager.setJtaDataSource(dataSource());
        Properties properties = new Properties();
        properties.put("eclipselink.weaving", "false");
        entityManager.setJpaProperties(properties);            entityManager.setPersistenceUnitName("entityManagerFactory2_product");
        return entityManager;

    }

}

application.yml

log:
  path: D:\log\work\dev
  appName: dewls
  level: info
server:
  port: 8888
  connection-timeout: 120000

spring:
  jta:
      enabled: true
      atomikos:
        datasource:
          jta-user:
            xa-properties.url: jdbc:mysql://xxxx:3306/dewls01?useUnicode=yes&characterEncoding=utf8&useSSL=true
            xa-properties.user: root
            xa-properties.password: 123
            xa-data-source-class-name: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
            unique-resource-name: jta-customer
            max-pool-size: 25
            min-pool-size: 3
            max-lifetime: 20000
            borrow-connection-timeout: 10000
          jta-product:
            xa-properties.url: jdbc:mysql://xxxxx/dewls02?useUnicode=yes&characterEncoding=utf8&useSSL=true
            xa-properties.user: root
            xa-properties.password: root
            xa-data-source-class-name: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
            unique-resource-name: order
            max-pool-size: 25
            min-pool-size: 3
            max-lifetime: 20000
            borrow-connection-timeout: 10000
  jpa:
    show-sql: true
    database: MySQLenter code here

После того, как я протестирую его, как показано ниже, используя postMan

@Service
public class JtaService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ProductRepository productRepository;

    @Transactional
        public void jtaTesting() {
        User user = new User();
        userRepository.save(user);

        Product product = new Product();
        productRepository.save(product);
    //        int i = 1 / 0;
    }
}

есть только один журнал, например:

[ INFO ] [2019-01-13 13:25:07] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/] [180] - Initializing Spring FrameworkServlet 'dispatcherServlet'

а также запись в БД не изменилась, что-то не так с моим кодом?

После того, как я изменил метод сохранения на метод saveAndFlush, он выдает исключение:

Описание исключения: транзакция в данный момент не активна; Вложенным исключением является javax.persistence.TransactionRequiredException: Описание исключения: транзакция в настоящее время не активна] с первопричиной javax.persistence.TransactionRequiredException: Описание исключения: в данный момент транзакция не активна в org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException (EntityTransactionWrapper.java:87) в org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.checkForTransaction (EntityTransactionWrapper.java:50) в org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction (EntityManagerImpl.java:2188) в org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush (EntityManagerImpl.java:967) at sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:497)

Я нашел решение ниже

  1. создание нового расширения контроллера из JTATransactionController

    public class AtomikosTransactionController extends JTATransactionController {
        private UserTransactionManager utm;
    
        public AtomikosTransactionController() {
            utm = new UserTransactionManager();
        }
        protected TransactionManager acquireTransactionManager() throws Exception 
        {
            return utm;
        }
    
        @Override
        public TransactionManager getTransactionManager() {
    
            return utm;
        }
    }
    
  2. добавить правильный файл в AtomikosTransactionController

properties.put ("eclipselink.target-server", "com.evan.jta.config.AtomikosTransactionController");

подробно проверьте на github

...