У меня уже есть 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)
Я нашел решение ниже
создание нового расширения контроллера из 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;
}
}
добавить правильный файл в AtomikosTransactionController
properties.put ("eclipselink.target-server", "com.evan.jta.config.AtomikosTransactionController");
подробно проверьте на github