Пакетная вставка OpenJpa - PullRequest
       12

Пакетная вставка OpenJpa

0 голосов
/ 20 марта 2019

Я уже прочитал это и это , но оно мне не подходит.У меня есть реализация openjpa, и мне нужно сделать пакетную вставку.У меня есть какая-то сущность, и с помощью Spring я внедряю свой менеджер транзакций и EntityManager из EntityManagerFactory, например

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="persistenceUnitName" value="JpaPersistenceUnit"/>
        <property name="jpaPropertyMap">
            <map>
                <entry key="openjpa.jdbc.DBDictionary" value="org.apache.openjpa.jdbc.sql.OracleDictionary" />
                <entry key="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
            </map>
        </property>
    </bean>

В классе у меня есть

@PersistenceContext
protected EntityManager em;
AtomicInteger size = new AtomicInteger();

@TransactionalRollback
public void saveLogs(Logs log) {

int i = size.incrementAndGet();
int batchSize=100;
em.persist(log);
if(i%batchSize==0){

em.flush();
em.clear();
}
}

И вот, я не знаю, чтоя должен делать.Потому что, если я использую flush (), я получаю ошибку, что я ничего не могу сделать с Shared EntityManager.Когда я только сохраняюсь, все в порядке, но все данные фиксируются немедленно.

Может быть, возможно сделать пакетную вставку с помощью SpringBuilder и некоторых из nativeQuery?Как

 String insert = "INSERT into SIEBEL_METHOD_LOGS (?1,?2,?3,?4) VALUES ";
    StringBuilder builder = new StringBuilder(insert);
        builder.append(
                "(" + log.getMethod() + "), "
                        + "(" + log.getClient() + "), "
                        + "(" + log.getStartDate() + "), "
                        + "(" + log.getResponseTime() + "), "
                        + "(" + log.getIsError() + ")");
            Query query = em.createNativeQuery(builder.toString());
            query.executeUpdate();

Но я не уверен в этом.

PS Кроме того, я не понимаю смысла того, что org.apache.openjpa.jdbc.sql.OracleDictionary имеет поле

// batch limit
   private int defaultBatchLimit = 100;

Когда это работает?Потому что всякий раз, когда я сохраняю и заканчиваю свой метод, я попадаю в БД, и это не зависит от 100 или 5 элементов, которые я сохранил в БД.Они будут там.

1 Ответ

0 голосов
/ 21 марта 2019

Я использовал это решение, но, возможно, возможно, больше элегантности

public class LoggerClass {
  private static final int batchSize = 100;
  private List<MethodsLog> logsList;
    private AtomicLong sizeList;

    private void initList() {
        this.logsList = new ArrayList<>(batchSize);
        this.sizeList = new AtomicLong();
    }
    public void saveLogs(MethodsLog log) {
        long i = sizeList.incrementAndGet();
        logsList.add(log.toJpa());
        if (i % batchSize == 0) {
            saveToDBAndClear(logsList);
            initList();
        }
    }

    private synchronized void saveToDBAndClear(List<MethodsLog> logs) {
        MethodsService.saveLogs(logs);
    }

    @TransactionalRollback
    public void saveLogs(List<MethodLogs> logs) {
        for (MethodLogs log : logs) {
            em.persist(log);
        }
    }
}
...