java - 当结果为列表时,JPA @OneToMany 不起作用

标签 java spring hibernate jpa

我正在使用 JPA、Spring boot。 当我获取包含购物车商品的订单时,使用 @OneToMany 注释。 我的域名代码如下。

订单:

@Data
@Entity
@Table(name="\"order\"")
@ToString
public class Order {

    @Id
    @GeneratedValue
    @Getter @Setter
    private Long id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name="order_id")
    @Getter @Setter
    private List<Cart> carts;

    public void addCart(Cart cart) {
        if (this.carts == null) {
            carts = new ArrayList<Cart>();
        }
        carts.add(cart);
    }
}

购物车:

@Data
@Entity
@Table(name="cart")
@ToString
public class Cart {

    @Id
    @GeneratedValue
    @Getter @Setter
    @Column(name="id")
    private Long id;

    @Column(name = "order_id")
    @Getter @Setter
    private Long orderId;

}

当我仅获取一个订单时,此方法非常有效,但当我获取两个以上订单时,此方法不起作用。我的意思是,当我只获取一个订单时,购物车字段的大小为 1 或更大,但是当我获取两个或更多订单时,购物车字段的大小为 0。

如何解决这个问题?预先感谢您!

最佳答案

如果不查看正在加载/查询实体的代码,几乎不可能找出提取问题所在。那么您能否将其添加到您的问题中?

同时,至少有一些事情可以改进,以获得更清晰的实体和更快的代码,也许这也可以帮助解决问题。

首先,您使用冗余配置,以及重新创建默认值的相应注释。

我假设是 lombok你正在使用什么,对吗?您可以删除两个实体中字段上的 @Getter@Setter 注释,并在类级别添加一次,以避免在每个字段上进行声明,但由于您是使用 @Data 你根本不需要它。与 @toString 相同,@Data 是所有这些(以及更多)的便捷注释。

@Data 的 JavaDoc 说:

Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}.

然后,尽管订单实体上的 @Table(name="\"order\"") 是必需的,因为 order 是某些 DBMS 中的保留字,但 @Table(购物车实体上的 name="cart") 是默认值。

接下来,我不建议对集合进行延迟初始化,因为与每次访问之前检查 null 时造成的损失相比,这样做通常没有任何好处。只需在声明中初始化它,您就不必再关心处理 null 了。除此之外,您应该考虑使用 Set 而不是购物车列表(这样您就不会出现重复项)。

还要考虑FetchType,因为EAGER仅在您使用分离实体并希望在每种情况下初始化关系时才有用。 LAZY@OneToMany 的默认设置,应该是首选。

您已经改进的一个事情是@JoinColumn,它将阻止 Hibernate(我厚颜无耻地假设您正在使用 Hibernate)创建连接表。但更重要的是考虑将 @OneToMany 转换为另一侧的 @ManyToOne 或使其双向。这将在读取(它还阻止连接表,因此需要更少的连接,更快的索引)和写入时间(由父端管理的关系)方面获得一些性能。

你对此有何看法:

@Data
@Entity
@Table(name="\"order\"")
public class Order {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Cart> carts = new HashSet<>();

}

还有这个:

@Data
@Entity
public class Cart {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    private Order order;

}

关于java - 当结果为列表时,JPA @OneToMany 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43001491/

相关文章:

java - 是否可以将 spring rest 文档与 spock 一起使用

java - Spring Security 3 - 总是返回错误 302

java - 通过JTA配置Spring + Hibernate JPA事务管理器

java - oracle中如何向已有的自增表插入一行?

Hibernate 资源池关闭过早

java - 读取fragment中的文件并将其放入listview中

java - 根据 JSON 模式验证 JSON(在 Java 中)

Java 清理步骤

java - 单元测试用例 MockRestServiceServer 预期的 url 不适用于 RestTemplate

Hibernate 条件按外键过滤