我正在尝试从EJB3 + JTA + JPA(EclipseLink)迁移应用程序。目前,该应用程序利用应用程序管理的持久上下文,因为设计时间数据库数量未知。
应用程序管理的持久化上下文允许我们控制如何创建EntityManager(例如提供不同的数据源JNDI以在运行时为特定的DB创建正确的EntityManager )。
E.g。
Map properties = new HashMap(); properties.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA"); //the datasource JNDI is by configuration and without prior knowledge about the number of databases //currently, DB JNDI are stored in a externalized file //the datasource is setup by operation team properties.put(PersistenceUnitProperties.JTA_DATASOURCE, "datasource-jndi"); properties.put(PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false"); properties.put(PersistenceUnitProperties.SESSION_NAME, "xxx"); //create the proper EntityManager for connect to database decided on runtime EntityManager em = Persistence.createEntityManagerFactory("PU1", properties).createEntityManager(); //query or update DB em.persist(entity); em.createQuery(...).executeUpdate();
当使用适当的TransactionAttribute(例如TransactionAttributeType.REQUIRED)部署在EJB容器(例如WebLogic)中时,容器将负责事务的开始/结束/回滚。
现在,我正在尝试将此应用程序迁移到Spring Boot。
我遇到的问题是,即使我使用@Transactional(propagation = Propagation.REQUIRED)
注释方法,也没有启动任何事务。
Spring应用程序打包为可执行JAR文件,并使用embadded Tomcat运行。
当我尝试执行这些更新API时,例如EntityManager.persist(..)
,EclipseLink总是抱怨:
javax.persistence.TransactionRequiredException:'目前没有任何交易活动'
以下示例代码:
//for data persistence @Service class DynamicServiceImpl implements DynamicService { //attempt to start a transaction @Transactional(propagation = Propagation.REQUIRED) public void saveData(DbJndi, EntityA){ //this return false that no transaction started TransactionSynchronizationManager.isActualTransactionActive(); //create an EntityManager based on the input DbJndi to dynamically //determine which DB to save the data EntityManager em = createEm(DbJndi); //save the data em.persist(EntityA); } } //restful service @RestController class RestController{ @Autowired DynamicService service; @RequestMapping( value = "/saveRecord", method = RequestMethod.POST) public @ResponseBody String saveRecord(){ //save data service.saveData(...) } } //startup application @SpringBootApplication class TestApp { public static void main(String[] args) { SpringApplication.run(TestApp.class, args); } } persistence.xml ------------------------------------------- <persistence-unit name="PU1" transaction-type="JTA"> <properties> <!-- comment for spring to handle transaction??? --> <!--property name="eclipselink.target-server" value="WebLogic_10"/ --> </properties> </persistence-unit> ------------------------------------------- application.properties (just 3 lines of config) ------------------------------------------- spring.jta.enabled=true spring.jta.log-dir=spring-test # Transaction logs directory. spring.jta.transaction-manager-id=spring-test -------------------------------------------
我的使用模式并未遵循大多数典型用例(例如,使用已知数量的数据库 - Spring + JPA + multiple persistence units: Injecting EntityManager)。
有人可以就如何解决这个问题给我建议吗?
有没有人遇到这种情况,设计时间内不了解DB?
谢谢。
答案 0 :(得分:0)
您自己已经回答了很多问题:“ 当部署在具有适当TransactionAttribute(例如TransactionAttributeType.REQUIRED)的EJB容器(例如WebLogic)中时,该容器将负责事务的开始/结束/回滚”。
WebLogic符合Java Enterprise Edition规范,这也许是它以前能工作的原因,但是现在您正在使用Tomcat(以嵌入式模式),而现在还没有。 因此,您根本无法做您想做的事情。 您的persistence.xml文件中的以下语句:
<persistence-unit name="PU1" transaction-type="JTA">
需要企业服务器(WebLogic,Glassfish,JBoss等)
使用Tomcat,您只能这样做:
<persistence-unit name="PU1" transaction-type="RESOURCE_LOCAL">
您需要自己处理交易:
myEntityManager.getTransaction.begin();
... //Do your transaction stuff
myEntityManager.getTransaction().commit();
答案 1 :(得分:0)
我终于可以使用它了:
添加交易内容
com.atomikos:transactions-eclipselink:3.9.3
(我的项目使用eclipselink而不是休眠)
org.springframework.boot:spring-boot-starter-jta-atomikos
org.springframework:spring-tx