Постоянная сущность JPA без инструкции persist()

У меня есть этот метод JPAServiceImpl:

@Override
@Transactional
public void createPageContent(SellerContent content, long userId) {

 Seller s = em.find(Seller.class,userId);
 content.setSeller(s);

 content.setSeller(s);
 s.addContent(content);
}

Он работает, но мне интересно, как он может работать, поскольку нет em.merge(seller) или em.persist(content).

Продавец получил CascadeType.ALL с отношениями SalesContent.

Не могли бы вы объяснить мне, если это нормальное поведение? Я бы написал как em.merge(seller) и em.persist(content). Это неправильно?

Например, я написал этот метод:

@Override
@Transactional
public void createFeedback(CartLine cartLine, String feedbackString) {
 Product product = cartLine.getProduct();

 Feedback feedback = new Feedback();
 feedback.setFeedbackContent(feedbackString);
 feedback.setCartLine(cartLine);
 cartLine.setFeedback(feedback);
 product.getFeedbacks().add(feedback);
 feedback.setProduct(product);

 em.persist(feedback);
 em.merge(cartLine);
 em.merge(product);
}

В этом методе я написал инструкции слияния и сохранения. Это неправильно?

2 ответа

Это работает, что ваш объект Seller загружается через менеджера объектов в той же транзакции. Во время выполнения он будет заменен прокси-объектом. Каждое изменение этого объекта будет автоматически сохраняться в конце транзакции. Вы можете проверить это очень просто: во время выполнения сделайте brakepoint в вашем методе createPageContent, затем проверьте фактический тип переменной Seller s. Это будет прокси-сервер, который необходим для следующих вещей:

  • Обнаруживать каждое изменение в состоянии Seller s (например, s.addContent(content)). Сохраняйте эти изменения в конце транзакции.
  • Загрузите ленивые отношения. Представьте, что у вашего Seller есть список Owner. По умолчанию во время выполнения этот список будет пустым. Он будет загружен точно в тот момент, когда вы выполните s.getOwners().iterator().

Поэтому обычно вам нужно вызвать em.persist() только для экземпляров, которые были созданы с использованием new ключевого слова. В большинстве случаев это необязательно: вы можете присоединить новый объект A к сохраненному объекту B а затем вызвать em.persist(B). A будет сохраняться каскадом.

Второй блок кода:

  • Я думаю, вы можете спокойно удалить вызовы em.merge. Слияние необходимо только при использовании CartLine mergedCartline = em.merge(cartLine); mergedCartline.doSomething() CartLine mergedCartline = em.merge(cartLine); mergedCartline.doSomething().
  • Вы можете удалить em.persist(feedback) если: a) CartLine cartLine всегда загружается через диспетчер сущностей; b) свойство cartLine.feedback может сохраняться каскадом (зависит от вашего отображения).


Поскольку ваше Entity находится в управляемом состоянии, вам не нужно вызывать percist().

licensed under cc by-sa 3.0 with attribution.