【问题标题】:Spring JPA - Many to one without full foreign objectSpring JPA - 多对一,没有完整的外来对象
【发布时间】:2018-07-27 10:49:40
【问题描述】:

我正在this repo 中试验 spring 和 jpa 的 ManyToOne。实体之间的关系是一个Cart(购物车)可以有多个Items(在this tutorial之后)。

购物车

@Entity
@Table(name="CART")
public class Cart 
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cart_id")
    private long id;


    @OneToMany(mappedBy = "cart")
    private Set<Item> items;

    /* rest of class*/

物品

@Entity
@Table(name="ITEMS")
public class Item
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;

    @Column(name="item_name")
    private String itemName;

    @ManyToOne
    @JoinColumn(name = "cart_id", nullable = false)
    private Cart cart; // needs an entire Cart instance :(

     /* rest of class*/

问题

如何将Items 映射到Cart 类而不使整个Cart 对象成为Item 类的一部分。

我想让Item 类看起来像这样

@Entity
@Table(name="ITEMS")
public class Item
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;

    @Column(name="item_name")
    private String itemName;


    @ManyToOne
    @JoinColumn(name = "cart_id", nullable = false)
    private long cartId; // just the ID of Cart, not the entire Cart object

这给出了错误

Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.example.demo.Item.cartId references an unknown entity: long
    at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:97) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1752) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1696) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1583) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278) ~[hibernate-core-5.2.12.Final.jar:5.2.12.Final]

这并不让我感到惊讶。但我希望能够以某种方式实例化一个 Item 而无需整个 Cart 实例。理想情况下,只需将Cart ID 作为Item 中的一个字段就足够了。

编辑

所以如果我必须在Item 中创建Cart 一个字段,如何使用data-h2.sql 脚本初始化数据库?没有 SQL 方法来表达 Cart 是什么!

【问题讨论】:

  • 您也可以在 items 上设置延迟获取,即 @OneToMany(mappedBy = "cart", fetch = FetchType.LAZY)
  • @ManyToOne 用于引用一个对象而不是原始类型,所以我认为当你实例化一个项目时,你不会实例化一个购物车对象,为了解决这个问题,你可以使用延迟加载机制.

标签: java hibernate spring-mvc spring-data-jpa


【解决方案1】:

您可以完全删除对Cart 的引用,并通过从@OneToMany 注释中删除mappedBy="cart" 部分来使完整的关系朝着一个方向发展。

如果您仍然想要项目中的cart_id,您可以使用Cart 上的java 代码进行设置。

当然,这一切都引出了一个问题:你为什么想要这种非常不符合 JPA 风格的行为。如果您创建另一个问题来说明您的原始问题/疑虑,则似乎有一些关于 JPA 的知识。

【讨论】:

  • 在我看来,Item 只存储了外键 cart_id 以及它自己的 id。这就是建立关系所需要的一切。将整个 Cart 对象放入 Item 对我来说似乎没有必要
  • 如果您更喜欢处理 id 而不是 JPA 可能不是正确的选择。此外,“似乎没有必要”的措辞暗示了使用对象引用的一些额外成本。开发人员方面当然不存在这种成本。而且,如果您处理商品,您可能会将购物车加载到任何地方,因此应该有最低限度的参考成本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-13
  • 2016-04-07
  • 1970-01-01
  • 2023-01-16
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多