Проект Spring Roo как пакетное задание без транзакций - PullRequest
3 голосов
/ 12 января 2011

У меня есть проект Roo, который работает "отлично" с транзакциями, но каждый .merge () или .persist () занимает все больше и больше времени, так что то, что должно было занять 10 мс, требует 5000 мс к концу транзакции. К счастью, мои изменения индивидуально идемпотентны, поэтому мне не нужна транзакция.

Но когда я выбрасываю обработку транзакций, я сталкиваюсь с классическим «контекст был закрыт», когда я выполняю myObject.merge ()

Я выполняю задание из командной строки в виде пакета, поэтому я обычно делаю вот что:

public static void main(final String[] args) {
    context = new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
    JpaTransactionManager txMgr = (JpaTransactionManager) context.getBean("transactionManager");
    TransactionTemplate txTemplate = new TransactionTemplate(txMgr);
    txTemplate.execute(new TransactionCallback() { @SuppressWarnings("finally")
    public Object doInTransaction(TransactionStatus txStatus) {
    try {
        ImportUnitFromDisk importer = new ImportUnitFromDisk();
        int status = importer.run(args[0]);
        System.out.println("Import data complete status: " + status);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        return null;
    }
    }});

    System.out.println("All done!");
    System.exit(0);
}

Но я действительно хочу сделать что-то вроде этого:

public static void main(final String[] args) {
    ImportUnitFromDisk importer = new ImportUnitFromDisk();
    int status = importer.run(args[0]);
    System.out.println("Import data complete status: " + status);
    System.out.println("All done!");
    System.exit(0);
}

Что я могу сделать, чтобы разрешить мне выполнять функции persist () и merge () без использования транзакций, учитывая, что сущности создаются с помощью Spring Roo (с использованием OpenJPA и MySQL)?

Приветствия

Nik

Ответы [ 2 ]

1 голос
/ 28 апреля 2012

У меня точно такая же проблема с производительностью в пакетном процессе Spring / Hibernate.Обратите внимание, что это не имеет ничего общего с Spring Roo или даже Spring - это связано с работой Hibernate / JPA.

Основная проблема заключается в том, что Hibernate поддерживает кэш сеанса всех объектов Java, которые являются частьютранзакции и для новых объектов (для которых инструментарий байт-кода не был выполнен) Hibernate должен сканировать объекты при каждой очистке, чтобы увидеть, были ли обновления.Это как минимум O (n) для n = # новых объектов в сеансе.Если пакетный процесс главным образом добавляет новые объекты, то это превращается в поведение O (n ^ 2) для всего пакета.

Одно решение, если вы хотите сохранить весь процесс в одной транзакции, - это периодически сбрасывать (делать вставки / обновления), а затем выселять сущности, которые вам больше не нужно хранить в сеансе.Другое решение - разделить пакетный процесс на несколько транзакций.

Подробнее см. http://www.basilv.com/psd/blog/2010/avoiding-caching-to-improve-hibernate-performance.

1 голос
/ 23 января 2011

Даже если ваши изменения идемпотентны, вам все равно потребуется транзакция.

Что касается производительности.

  1. Насколько тесно связаны объекты вашей сущности. (Например, если все ссылки на таблицы fk переносятся в отношения сущностей, то они довольно тесно связаны)?

  2. Может быть, вам следует удалить некоторые нежелательные двунаправленные отношения.

  3. Определение основных таблиц и удаление сущностей, сопоставленных с основными записями.

  4. Какие у вас варианты каскада? Проверьте, есть ли у вас все варианты каскада.

Для меня это выглядит так, что карта сущностей слишком тесно связана (все знают кого-то, у кого есть ...), и каскадные опции начинают слияние целого графа объектов. (зарегистрируйте свой jpa sql, который может подтвердить мое предположение)

...