在RestEasy端点中的两个不同EntityManager之间迁移数据

时间:2014-07-03 23:46:02

标签: jpa resteasy

我使用RestEasy端点在SQL Server数据库和Oracle数据库之间迁移数据。我在JBoss上定义了两个数据源

<?xml version="1.0" encoding="UTF-8"?>
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
    <datasource jndi-name="java:jboss/datasources/oracleDS"
                pool-name="oracle" enabled="true"
                use-java-context="true">
        <connection-url>jdbc:oracle:thin:@127.0.0.1:1521:XE</connection-url>
        <driver>oracle</driver>
        <pool>
            <min-pool-size>10</min-pool-size>
            <max-pool-size>100</max-pool-size>
            <prefill>true</prefill>
            <use-strict-min>false</use-strict-min>
            <flush-strategy>FailingConnectionOnly</flush-strategy>
        </pool>
        <security>
            <user-name>SOURCE</user-name>
            <password>source</password>
        </security>        
    </datasource>
    <datasource jndi-name="java:jboss/datasources/sqlserverDS" pool-name="sqlserver"
        enabled="true" use-java-context="true">
        <connection-url>jdbc:sqlserver://localhost:1433;databaseName=DEST</connection-url>
        <driver>sqlserver</driver>
        <pool>
            <min-pool-size>10</min-pool-size>
            <max-pool-size>100</max-pool-size>
            <prefill>true</prefill>
            <use-strict-min>false</use-strict-min>
            <flush-strategy>FailingConnectionOnly</flush-strategy>
        </pool>
        <security>
            <user-name>DEST</user-name>
            <password>dest</password>
        </security>
    </datasource>
</datasources>

我的persistence.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="         http://java.sun.com/xml/ns/persistence         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="primary">
        <jta-data-source>java:jboss/datasources/oracleDS</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="none"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
        </properties>
    </persistence-unit>
    <persistence-unit name="secondary" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/sqlserverDS</jta-data-source>
        <class>com.foobar.model.sqlserver.SourceEntity</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="none"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

我的RestEasy端点

package com.foobar.rest;

import com.foobar.model.DestEntity;
import com.foobar.model.sqlserver.SourceEntity;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;

/**
 *
 * @author Andres
 */
@Stateless
@Path("/endpoint")
public class FoobarEndpoint {

    private static final Logger logger = Logger.getLogger(FoobarEndpoint.class);

    @PersistenceContext(unitName = "primary")
    private EntityManager csEm;

    @PersistenceContext(unitName = "secondary")
    private EntityManager vhEm;

    @GET
    @Path("/migration")
    public Response migration() {
        logger.trace("Starting migration process");

        TypedQuery<SourceEntity> sourceQuery = this.vhEm.createNamedQuery("SourceEntity.findAll", SourceEntity.class);
        List<SourceEntity> sourcePeriodsList = sourceQuery.getResultList();

        this.csEm.createNamedQuery("DestEntity.deleteAll").executeUpdate();
        int i = 0;
        for (SourceEntity sourcePeriod : sourcePeriodsList) {
            DestEntity entity = new DestEntity();
            // Set DestEntity fields
            entity = this.csEm.merge(entity);
        }

        return Response.noContent().build();
    }

}

在我从源检索数据并尝试从目标中删除数据后出现问题,JBoss给出了这个错误:

javax.transaction.SystemException: IJ000356: Failed to enlist: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 0:ffff7f000001:-47dbad9f:53b43ae8:a38 status: ActionStatus.ABORT_ONLY >

显然,它尝试在同一个事务中执行这两个操作,并且由于它们来自不同的服务器,因此无法执行此操作。

任何解决方法的想法?

1 个答案:

答案 0 :(得分:0)

我不能按照我想要的方式去做。我最后使用普通JDBC查询源代码并使用JPA插入目标。