2

我正在使用 Spring Data 和 Apache Camel 进行项目,我们有 2 个数据库,Sql Server 和 Oracle 以及 JTA。出现问题是因为我需要从一个大文件(大约 10000000 条记录)中插入数据,所以我决定使用批量插入作为:

@PersistenceContext(unitName="persistenceUnitSql")
EntityManager em;

public void insertBatch() {
    em.getTransaction().begin();
    for (int i = 1; i <= 1000000; i++) {
      Point point = new Point(i, i);
      em.persist(point);
      if ((i % 10000) == 0) {
          em.getTransaction().commit();
          em.clear();          
          em.getTransaction().begin();
      }
    }
    em.getTransaction().commit();
}

但发生了这个问题:

    A JTA EntityManager cannot use getTransaction()

任何帮助...

4

2 回答 2

1

自我控制 JTA 事务似乎比想象的要困难得多。我通常使用的一种解决方法是拥有一个单独的“服务”来执行一批插入,然后在该方法上设置 REQUIRES_NEW 事务传播策略,所以它看起来像:

class FooService {

    private PointPersister pointPersister;

    @Transactional(propagation=REQUIRED)
    public void insertBatch() {
        List<Point> points = new ArrayList<Point>(10000);
        for (int i = 1; i <= 1000000; i++) {
            points.add(new Point(i,1));
            if ((i % 10000) == 0) {
                pointPersister.insertPointBatch(points);
            }
        }
    }
}

class PointPersisterImpl implements PointPersister {
    @PersistenceContext
    private EntityManager em;

    @Transactional(propagation=REQUIRES_NEW)    // in a separate txn
    public void insertPointBatch(List<Point> points) {
        // persist points
    }
}

您还可以做出其他选择来避免处理麻烦且容易出错的手动事务处理。 Spring Batch是可能的解决方案之一。

于 2013-11-14T01:54:51.730 回答
0

我通过以下方式解决了这个问题:

@PersistenceUnit(unitName="persistenceUnitSql") 
// from persistence xml <persistence-unit name="persistenceUnitSql" transaction-type="JTA"> 
private EntityManagerFactory emf;

@Autowired
private JtaTransactionManager transactionManagerSqlServer;
// from application-context.xml
//<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="transactionManagerSqlServer" />

public List<Point> insertBatch(List<Point> datos) {

    try {
        UserTransaction transaction = transactionManagerSqlServer.getUserTransaction();     
        transaction.begin();
        EntityManager em = emf.createEntityManager();

        for (Point punto : datos) {
            em.persist(punto);
        }
        transaction.commit();
        em.close();
    } catch (NotSupportedException e) {
        LOGGER.error(e);
    } catch (SystemException e) {
        LOGGER.error(e);
    } catch (SecurityException e) {
        LOGGER.error(e);
    } catch (IllegalStateException e) {
        LOGGER.error(e);
    } catch (RollbackException e) {
        LOGGER.error(e);
    } catch (HeuristicMixedException e) {
        LOGGER.error(e);
    } catch (HeuristicRollbackException e) {
        LOGGER.error(e);
    }       

    return datos;
}
于 2013-11-14T21:35:56.650 回答