Как предотвратить исключение LazyInitializationException на этапе Spring Batch с параллельными фрагментами и лениво загрJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как предотвратить исключение LazyInitializationException на этапе Spring Batch с параллельными фрагментами и лениво загр

Сообщение Anonymous »

Я работаю над заданием Spring Batch с параллельной обработкой фрагментов. Проблема, с которой я столкнулся, — это LazyInitializationException из-за вложенных коллекций с отложенной загрузкой в ​​моих объектах JPA.
Я использую JpaPagingItemReader для чтения, JpaTransactionManager< /code> для управления транзакциями и SimpleAsyncTaskExecutor для параллельной обработки.
Настройка:
  • Spring Boot: 3.3.4
  • Spring Batch: 5.1.2
  • Диспетчер транзакций: JpaTransactionManager
    Исполнитель задач: SimpleAsyncTaskExecutor
Простой пример:Субъект клиента:
@Entity
public class Customer {

@Id
private Long id;

@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
}

Сущность заказа:
Отношение @OneToMany по умолчанию равно FetchType.LAZY .
@Entity
public class Order {

@Id
private Long id;

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List types;

// Other @OneToMany collection fields...

}

Конфигурация пакетного шага Spring:
Я использую JpaPagingItemReader и ItemProcessor. Этот шаг распараллеливается с помощью SimpleAsyncTaskExecutor.
@Bean
public JpaPagingItemReader customerItemReader(EntityManagerFactory entityManagerFactory) {
return new JpaPagingItemReaderBuilder()
.name("customerItemReader")
.entityManagerFactory(entityManagerFactory)
.queryString("SELECT c FROM Customer c")
.pageSize(100)
.build();
}

@Bean
public Step processCustomersStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
JpaPagingItemReader customerItemReader,
ItemProcessor customerItemProcessor,
ItemWriter customerItemWriter,
TaskExecutor taskExecutor) {
return new StepBuilder("processCustomersStep", jobRepository)
.chunk(100, transactionManager)
.reader(customerItemReader)
.processor(customerItemProcessor)
.writer(customerItemWriter)
.taskExecutor(taskExecutor)
.build();
}

При запуске пакетного задания я получаю следующую ошибку при доступе к отложенному заказу или коллекции его вложенных типов в ItemProcessor:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.myapp.Order.types: could not initialize proxy - no Session

Что я пробовал:
  • Извлечение с помощью JOIN FETCH : Я не могу использовать JOIN FETCH, потому что
    OrderОбъект содержит несколько вложенных коллекций с отложенной загрузкой,
    что приводит к большим и неэффективным запросам.
  • Поскольку я использую JpaTransactionManager, я предполагал, что он справится
    область транзакции правильно, но исключение LazyInitializationException
    по-прежнему возникает при доступе к вложенным лениво загруженным коллекциям в
    ItemProcessor.
Вопрос:
Как предотвратить исключение LazyInitializationException на этапе Spring Batch с параллельными фрагментами, когда используя JpaPagingItemReader и JpaTransactionManager?
Должен ли я обрабатывать EntityManager по-другому или есть другой шаблон для обработки сущностей с вложенными коллекциями с отложенной загрузкой в параллельно?
ОБНОВЛЕНИЕ (процессор, средство записи и менеджер транзакций JPA)
Обработчик элементов:
В ItemProcessor я создаю новый экземпляр Customer и копирую вложенный Order и связанные с ним типы. Для этого требуется доступ к лениво загруженным коллекциям в ItemProcessor, где и возникает исключение LazyInitializationException.
@Component
public class CustomerItemProcessor implements ItemProcessor {

@Override
public Customer process(Customer customer) throws Exception {
Customer newCustomer = new Customer();
Order order = new Order();
order.setTypes(customer.getOrder().getTypes()));
newCustomer.setOrder(order);
return newCustomer;
}

}

Запись элемента:

ItemWriter использует внедренный EntityManager для сохранения обработанных объектов.
@Component
public class CustomerItemWriter implements ItemWriter {

private final EntityManager entityManager;

public CustomerItemWriter(EntityManager entityManager) {
this.entityManager = entityManager;
}

@Override
public void write(Chunk

Подробнее здесь: https://stackoverflow.com/questions/790 ... arallel-ch
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»