Davis
Davis

Reputation: 308

Spring mutual relationship of entities

I have the following user entity.

@Entity
@JsonIgnoreProperties(value = {"createdAt", "updatedAt", "roles", "enabled",
    "authorities", "credentialsNonExpired", "accountNonLocked", "accountNonExpired"})
@Data
@Accessors(chain = true)
public class User extends Base implements UserDetails, Serializable {

@Size(min = 4, max = 20)
@NotNull
private String username;

@NotNull
private String password;

@NotNull
@Email
private String email;

@ElementCollection(fetch = FetchType.EAGER)
private List<Role> roles = new ArrayList<>();

private List<Book> bookList = new ArrayList<>();

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return roles.stream().map(r -> new SimpleGrantedAuthority(r.toString())).collect(Collectors.toList());
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    return true;
}
}

I want user to have a list of books but I am facing different kind of error in different trials. When I put @OneToMany annotation over bookList attribute, I get this error

failed to lazily initialize a collection of role: com.example.demo.model.User.bookList, could not initialize proxy - no Session

In some sources, it said to use @OneToMany like @OneToMany(mappedBy = "xxx", cascade = CascadeType.ALL, fetch = FetchType.EAGER) and in this case in the Book entity, I should add user attribute and use @ManyToOne but I do not want book entity to have user attribute. How can I handle this?

This is getBooks method in User service.

@Transactional
public GenericResponse findAllBooks(User user) {
    Objects.requireNonNull(user);
    return genericResponseService.createResponseNoError(user.getBookList());
}

And I cannot have to fetchtype eager attribute in the same model, it throws

Unable to build Hibernate SessionFactory; nested exception is org.hibernate.loader.MultipleBagFetchException

Note: I do not want to use EAGER fetch type.

Upvotes: 0

Views: 182

Answers (1)

omar jayed
omar jayed

Reputation: 868

In my understanding, you want to map User to Book as OneToMany. But only in one direction, from User to Book, not the other way around. For this purpose, you can use unidirectional OneToMany mapping.

public class User extends Base implements UserDetails, Serializable {
    ...

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name="book_id")
    private List<Book> bookList = new ArrayList<>();

    ....
}

Note: You'll need JPA2.X for this, it's not supported by JPA1.0. You learn more about how to use @JoinColumn here

Upvotes: 1

Related Questions