Вылетает org.hibernate.LazyInitializationException

245
23 апреля 2019, 23:10

Модель мини магазина

User:

@Entity
@Table(name = "users")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@Transient
private String password2;
private String email;
//...
@OneToOne(mappedBy = "user", fetch = FetchType.EAGER)
private Cart cart;
//getters and setters

Cart:

@Entity
@Table(name = "carts")
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "cart")
private List<BuyProduct> buyProducts;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
//getters and setters

BuyProduct:

@Entity
@Table(name = "buyproduct")
public class BuyProduct {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "product_id")
private Product product;
@ManyToOne
@JoinColumn(name = "cart_id")
private Cart cart;
//getters and setters

Product:

@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String productname;
private String description;
@OneToMany(mappedBy = "product")
private List<BuyProduct> buyProducts;
private Long price;
//getters and setters

Здесь я пытался создать в одном из контроллеров мапу на продукт -> количество продуктов в корзине.

@GetMapping
public String cart(@AuthenticationPrincipal User user,
                     @PageableDefault(sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable,
                     Model model) {
    Map<Product, Integer> productMap = new HashMap<>();
    for (BuyProduct currentBuyProduct : user.getCart().getBuyProducts()) {
        Product product = currentBuyProduct.getProduct();
        if (productMap.containsKey(product)) {
            int count = productMap.get(product);
            productMap.put(product, ++count);
        } else {
            productMap.put(product, 1);
        }
    }
    //...
}

Но в строчке с условием цикла вылетает ошибка org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ru.study.simpleshop.models.Cart.buyProducts, could not initialize proxy - no Session

Пробовал ставить в Cart @OneToMany(mappedBy = "cart", fetch = FetchType.EAGER), так там вообще сервер не поднимается. Пробовал метить с помощью Transactional - тоже не помогает. Ощущение, что я просто модель неверно выстроил.

Answer 1

Попробую угадать.

Эта ошибка вылетает при попытке вытащить ленивую коллекцию через user-а, который @AuthenticationPrincipal User user?

Смущает этот @AuthenticationPrincipal. User во время логина извлекается из базы и сохраняется где-то в сессии http в качестве принципала?
Тогда при последующих запросах он и сущности, на которые он ссылается, практически стопудова больше не привязаны ни к какой сессии и транзакции в манагере сущностей. И поэтому из него больше нельзя извлечь ленивые коллекции.

Вам нужно каждый раз извлекать свежую копию user-а. Примерно (очень примерно, потому что даже близко не знаю как там через спринг это делается) так

public String cart(@AuthenticationPrincipal User user,
                 @PageableDefault(sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable,
                 Model model) {
    user = entityManager.find(User.class, user.getId());
    Map<Product, Integer> productMap = new HashMap<>();
    for (BuyProduct currentBuyProduct : user.getCart().getBuyProducts()) {
Answer 2

1) Помечайте функцию получения продукта из базы @Transactional 2) Если уже это не поможет то, переопределяйте этот бин в конфиге

@Bean
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
    return new OpenEntityManagerInViewFilter();
}
READ ALSO
AdMob показ рекламы в авиарежиме

AdMob показ рекламы в авиарежиме

Мне показали приложение в App Store в котором реклама показывается даже в авиарежиме, причём каждый раз разная (речь о Rewarded Video и Interstitial)Как это...

165
Исключение работает не верно [дубликат]

Исключение работает не верно [дубликат]

На данный вопрос уже ответили:

139
Изменение заставочной картинки на телефоне Android

Изменение заставочной картинки на телефоне Android

Возможно ли изменить заставочный экран на телефоне Android программно(на изображение, например)? Если да, то как, используя Java

114