2012-03-15 2 views
3

Я использую Spring 3, JPA + Hibernate для приложения CMS. В этом приложении у меня есть метод класса обслуживания, который аннотируется с @Transactional Аннотация с rollBack. Внутри этого метода я вставляю данные (т.е. классы сущностей) в таблицу с использованием цикла. Для каждого iteration классов сущности цикла необходимо сохранить в базе данных. Но этого не происходит. Фиксирование происходит только тогда, когда выполнение цикла завершено и выходит из метода. Затем он фиксирует и сохраняет все сразу. Но мне нужно прочитать данные, как только они будут вставлены в базу данных, прежде чем совершать в этом случае. Я пробовал с ISOLATION LEVEL, чтобы читать uncommitted, но он не поддерживался, так как я использую значение по умолчанию JPADialect. Также попытался добавить hibernate реализация jpaDialect, но все же это не сработало. Пожалуйста, помогите с обходным решением этой проблемы. Еще одна вещь, есть ли какой-либо способ использования метода, необходимого для распространения.@Transactional Annotation + для ввода данных в петлю

+0

Вы, кажется, поняли, в чем проблема. Вы только что потеряли свои границы транзакций. Как только вы исправите это, вы должны обнаружить, что он работает так, как ожидалось. –

+0

Вы должны иметь возможность читать неработающие данные внутри одной транзакции без фиксации или изменения уровня изоляции. Насколько я знаю, это наиболее распространенное поведение. –

ответ

5

удалите транзакционную аннотацию по методу с циклом.

В цикле называют отдельный метод для выполнения сохранения, делает этот метод транзакционного

+0

Спасибо за ваш ответ @NimChimpsky, но у меня есть Transactional Annotation на уровне класса, даже если я удалил аннотацию Transactional из метода с помощью цикла и передал его другому методу в том же классе. Это не сработает, так как аннотации уровня класса уже присутствуют. Есть ли способ, которым я могу указать аннотацию Transactional на уровне класса, чтобы игнорировать некоторые методы, определенные в этом классе, то есть не для рассмотрения управления транзакциями. – Krishna

+0

просто удалите аннотацию уровня класса и добавьте ее к каждому методу, который вы хотите – NimChimpsky

+1

Я попытался с этим, но когда я запустил приложение, он выдает TransactionRequiedException, говорящий, что «транзакция не выполняется». Я создал два метода, в классе службы одним методом я написал некоторые бизнес-логики, а во втором методе я написал коды для создания классов сущностей и ссылался на класс DAO для сохранения этого класса сущности. Для первого метода я не дал никакой аннотации, но для второго метода, аннотированного аннотацией Transactional с распространением. Требуется новое свойство. Выполнение начинается с первого метода. – Krishna

11

Вы правы, это то, что I означает в . Поскольку транзакции работают изолированно, другие транзакции не могут видеть их до их совершения. Но играть с уровнями изоляции - это плохая практика. Я бы посоветовал вам запускать каждую итерацию в отдельной транзакции с запуском и фиксацией внутри.

Это немного сложно весной, но вот пример:

public void batch() { 
    for(...) { 
     insert(...) 
    } 
} 

//necessarily in a different class! 
@Transactional 
public void insert() { 

} 

Обратите внимание, что batch() является не с аннотацией @Transactional и insert() должен быть в другом классе (весна обслуживание). Слишком долго комментировать, но это жизнь. Если вам это не нравится, вы можете использовать TransactionTemplate вручную.

+0

Я хотел бы использовать TransactionTemplate для решения этой проблемы, но я использую подход Declarative Transaction для других классов обслуживания. Это плохое поведение для смешивания программных транзакций с использованием TransactionTemplate с декларативными транзакциями. – Krishna

1

Вы либо должны пойти с программными транзакциями (Spring, TransactionTemplate или PlatformTransactionManager являются классами, чтобы смотреть на, см Spring Doc for programmatic transactions, или вы можете вызовите другой транзакционный метод из вашего цикла, где транзакция отмечена Propagation.REQUIRES_NEW, что означает, что каждый вызов этого метода выполняется в его собственной транзакции, см. here. Я думаю, что для второго подхода вам необходимо определить метод REQUIRES_NEW для другого компонента Spring из-за AOP-Proxy. Вы также можете опустить REQUIRES_NEW, если цикл не выполнен в транзакции.

Смежные вопросы