1

My goal was to pass a List of Businesses to the model from the controller to display it in a view and I have succeeded, but have a bit of confusion.

When I initially tried using:

public User getCurrentAuthenticatedUser() {
    UserDetailsImpl user = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    return user.getUser();
}

@GetMapping("")
public String list(Model model) {
    model.addAttribute("businesses", userService.getCurrentAuthenticatedUser().getBusinesses());
    return "business/list";
}

I got this error: "failed to lazily initialize a collection of role: com.xyz.User.businesses could not initialize proxy - no Session"

Then I tried:

@GetMapping("")
public String list(Model model) {
    int userId = userService.getCurrentAuthenticatedUser().getId();
    User user = userService.getById(userId); // gets User using Spring Data JPA UserRepository 
    List<Business> businesses = user.getBusinesses();
    model.addAttribute("businesses", businesses);
    return "business/list";
}

And this worked perfectly fine.

What was the issue using the first method. It seemed more simple rather than calling a User from the UserRepository. I've seen some posts that say you should use EAGER fetching, but that's just seems like a bandaid solution. From the beginner's understanding: Since fetch type is LAZY the businesses don't exist yet in the User but are fetched on demand later on so there shouldn't be an issue. Edit: After more thought I remembered that with basic Hibernate you would have to create Transactions and commit transactions. I'm assuming that User is not within a Transaction that's why I can't get businesses using the 1st method. What would be a better solution to fetch the current Authenticated user? And that user's attributes such as a list of businesses.

Model Classes: Business:

@Entity
@Table(name = "businesses")
public class Business {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private LocalDate date;

@ManyToOne(cascade={CascadeType.MERGE})
@JoinColumn(name="user_id")
private User user;

public Business() {
}

public Business(String name, String description, LocalDate date, User user) {
    ...
}

public Business(Long id, String name, String description, LocalDate date, User user) {
    ...
}
... getters/setters

}

USER:

@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
private boolean enabled;
 
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable( name = "users_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();

@OneToMany(fetch = FetchType.LAZY, mappedBy="user", cascade={CascadeType.MERGE}) 
private List<Business> businesses;

... getters/setters

}

NoobSailboat
  • 109
  • 9
  • Does this answer your question? [How to solve the “failed to lazily initialize a collection of role” Hibernate exception](https://stackoverflow.com/questions/11746499/how-to-solve-the-failed-to-lazily-initialize-a-collection-of-role-hibernate-ex) – Toni Dec 05 '22 at 18:28
  • Do you have (by incidence) `spring.jpa.open-in-view=true` (resp. not set)!? ..this would explain, why it works – xerx593 Dec 05 '22 at 18:50
  • Hi! I'm looking for an explanation to the same question. Have you found anything? – Davide C Mar 21 '23 at 12:57

0 Answers0