Spring JPA - Many to one without full foreign obje

2019-07-14 01:59发布

I am experimenting with spring and jpa's ManyToOne in this repo. The relationship between the entities is that one Cart (shopping cart) can have many Items (following this tutorial).

Cart

@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*/

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 Cart cart; // needs an entire Cart instance :(

     /* rest of class*/

Question

How can I map the Items to the Cart class without making the entire Cart object part of the Item class.

I want to look the Item class to look like this

@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

This gives the errors

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]

which doesn't really surprise me. But I want to be somehow able to instantiate an Item without an entire Cart instance. Ideally, just the Cart ID as a field in Item would suffice.

EDIT

So if I have to make Cart a field in Item how to I initialize the db with a data-h2.sql script? There is no SQL way to express what a Cart is!

1条回答
▲ chillily
2楼-- · 2019-07-14 02:40

You can just remove the reference back to the Cart completely and make the complete relationship go just in one direction by dropping the mappedBy="cart" part from the @OneToMany annotation.

If you still want the cart_id in the item you can set it using java code on the Cart.

Of course, all this begs the question: Why do you want this behavior which is very un-JPA-ish. If you create another question stating your original question/concern it seems likely that there is something to learn about JPA.

查看更多
登录 后发表回答