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

时间:2017-03-24 14:01:23

标签: java spring hibernate jpa

我正在使用JPA,Spring启动。 当我获取包含购物车商品的订单时,使用@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。

我该如何解决这个问题?提前谢谢!

2 个答案:

答案 0 :(得分:0)

订单类:

public class Order {

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

    @OneToMany(mappedBy="orderId" fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @Getter @Setter
    private Set<Cart> carts;

}

购物车类:

public class Cart {

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

    @ManyToOne
    @Getter @Setter
    private Order orderId;

}

例如:JPA OneToMany and ManyToOne Relationships

我只是写了改变。 我希望它能起作用

答案 1 :(得分:0)

如果没有看到加载/查询实体的代码,几乎不可能找出提取问题。那么请你把它添加到你的问题中吗?

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

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

我认为你使用的是lombok,对吧?您可以删除两个实体中字段的@Getter@Setter注释,并在类级别添加一次以避免在每个字段上声明,但由于您使用的是@Data,根本不需要它。与@toString相同,@Data是所有内容的便利注释(以及更多内容)。

@Data的JavaDoc说:

  

相当于{@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}。

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

接下来,我不建议对集合进行延迟初始化,因为与在每次访问之前检查null时所造成的惩罚相比,通常没有任何好处。只需在声明中初始化它,您就不必再关心处理null了。除此之外,你应该考虑使用一个Set而不是一个List列表(所以你没有重复)。

还要考虑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;

}