Mini store model

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 

Here I tried to create a map for a product in one of the controllers -> the number of products in the basket.

 @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); } } //... } 

But in the line with the condition of the cycle, the error org.hibernate.LazyInitializationException: failed to get the initialize a collection of role: ru.study.simpleshop.models.Cart.buyProducts, could not initialize proxy - no Session

Tried to put in Cart @OneToMany (mappedBy = "cart", fetch = FetchType.EAGER), so there generally the server does not rise. Tried to mark with Transactional - also does not help. The feeling that I just built the model incorrectly.

    2 answers 2

    I'll try to guess.

    This error crashes when you try to pull out a lazy collection through the user, which is @AuthenticationPrincipal User user?

    Confused by this @AuthenticationPrincipal. User during login is retrieved from the database and saved somewhere in the http session as a principal?
    Then, in subsequent requests, he and the entities to which he refers are practically no longer tied to any session or transaction in the entity manager. And therefore it is no longer possible to extract lazy collections from it.

    You need to extract a fresh copy of the user each time. Approximately (very approximately, because I don’t even know very well how it is done there through the spring) so

     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()) { 
    • Yes, cool, thanks) Only I use the repositories, so instead of entityManager I logged in the UserRepository, roughly speaking, but I understood the logic. I probably didn’t understand this badly @AuthenticationPrincipal. I look like the user arrives automatically. It seems like it should not have failed. But it turns out that everything is not so simple :) And yes, everything works, I checked it) - global_silence
    • By the way, it is also necessary to mark with an annotation Transactional. Without this, the same error will crash. - global_silence Nov.

    1) Mark the function of receiving the product from the @Transactional database 2) If it does not help then, override this bin in the config file

     @Bean public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() { return new OpenEntityManagerInViewFilter(); }