【问题标题】:Spring mutual relationship of entitiesSpring实体的相互关系
【发布时间】:2020-07-13 16:19:20
【问题描述】:

我有以下用户实体。

@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;
}
}

我希望用户有一个书籍列表,但我在不同的试验中面临不同类型的错误。当我将 @OneToMany 注释放在 bookList 属性上时,出现此错误

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

在某些消息来源中,它说要使用 @OneToMany,例如 @OneToMany(mappedBy = "xxx", cascade = CascadeType.ALL, fetch = FetchType.EAGER),在这种情况下,在 Book 实体中,我应该添加用户属性并使用 @ManyToOne 但我不希望 book 实体具有用户属性。我该如何处理?

这是用户服务中的 getBooks 方法。

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

而且我不必在同一个模型中获取类型急切属性,它会抛出

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

注意:我不想使用 EAGER 提取类型。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    据我了解,您希望将 User 映射到 Book 作为 OneToMany。但只有一个方向,从用户到书,而不是相反。 为此,您可以使用单向 OneToMany 映射。

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

    注意:您需要 JPA2.XJPA1.0 不支持。 你了解更多关于如何使用@JoinColumnhere

    【讨论】:

    • 但这使用了 EAGER 抓取。
    • @Davis 您可以将获取类型设置为 LAZY。但是你不应该尝试从数据库事务之外的User 对象访问bookList,否则你会得到一个惰性初始化异常,你是否已经经历过。 (您需要知道事务的边界在哪里,并且只能在事务内部访问bookList)。
    • 将其更改为 FetchType.LAZY,然后使用 -> JOIN FETCH (JPQL) 获取数据。 String String = "select u from User u join fetch u.books b where u.username = :username".而且您的实体类没有@Id 字段..
    • 我在 get books 方法中首先使用 findByUsername 处理了这个问题。所以它加载了惰性数据。
    • @OneToMany 的默认获取类型是 Lazy。因此,在这种情况下无需明确提及。
    猜你喜欢
    • 2020-04-03
    • 2016-05-02
    • 1970-01-01
    • 2021-05-22
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-17
    相关资源
    最近更新 更多