Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring数据Rest/JPA级联在补丁上持久化_Java_Jpa_Spring Data Rest - Fatal编程技术网

Java Spring数据Rest/JPA级联在补丁上持久化

Java Spring数据Rest/JPA级联在补丁上持久化,java,jpa,spring-data-rest,Java,Jpa,Spring Data Rest,我有两个实体,Book和BookEvent。它们通过一种多对一关系联系在一起,即一本书可以有许多BookEvents。 我将Book视为聚合根目录,并为Book实体(而不是BookEvent)拥有一个存储库 @Entity @Table(name = "book") public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; priva

我有两个实体,Book和BookEvent。它们通过一种多对一关系联系在一起,即一本书可以有许多BookEvents。 我将Book视为聚合根目录,并为Book实体(而不是BookEvent)拥有一个存储库

@Entity
@Table(name = "book")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<BookEvent> events = new ArrayList<>();


    public List<BookEvent> getEvents() {
        return events;
    }

    public void setEvents(List<BookEvent> events) {
        for (BookEvent event: events) {
            event.setBook(this);
        }
        this.events = events;
    }

    public void addEvent(BookEvent event) {
        events.add(event);
        event.setBook(this);
    }

    public void removeEvent(BookEvent event) {
        events.remove(event);
        event.setBook(null);
    }
}
现在,我想在创建图书后向图书添加一个新事件。我使用Spring数据Rest

用一篇文章和一个事件创建一本书效果很好:

{
    "title": "My example book",
    "events": [ 
        {
            "type": "BOUGHT",
            "date": "2017-05-09"
        }
        ]
}
答案是:

{
    "title": "My example book",
    "events": [
        {
            "id": 3,
            "date": "2017-05-09",
            "_links": {
                "book": {
                    "href": "http://localhost:8080/api/books/2"
                }
            }
        }
    ]
}
但是如果我接着做一个JSON补丁来附加一个新事件,那么该事件将包含在对补丁请求的响应中,但它实际上不会保存在数据库中。之后,GET on the book不会返回该事件,并且当数据库中的book_id列为null时

[
    {
    "op": "add",
    "path": "/events/-",
    "value": 
        {
            "date": "2017-05-09"
        }
}
]
使用调试器时,在初始POST请求时调用setEvents方法,但在补丁请求期间,仅调用getEvents方法-无setBook或addEvent方法。我认为问题就在那里


我的实体设置有问题吗?

问题是我的设置是双向的一个实体设置,没有联接表。问题可以通过两种方式解决:

创建联接表。这是通过向Book类的events属性添加@JoinTable注释来实现的。这需要在数据库中增加一个表,因此我没有选择这种方式。 使用单向OneToMany设置,请参见。这仅由JPA2.x支持,但在SpringBoot2.0安装中没有问题。通过这种方式,实现看起来非常干净。 我的代码现在如下所示:

@Entity
@Table(name = "book")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(cascade = ALL) //The cascade is important as otherwise a new event won't be saved.
    @JoinColumn(name="book_id", referencedColumnName = "id")
    private List<BookEvent> events = new ArrayList<>();

    //Standard getter and setter for getEvents() and setEvents()
}

@Entity
public class BookEvent {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name="book_id")
    private Long bookId;

    //No getter/setter for bookId was necessary
}

不需要更新交互链接的特殊getter/setter。这将获得一个带有SDR的干净JSON响应,每个事件上都没有_links属性。添加和删除新条目同样有效。

man我已经做了与您类似的所有事情,但在持久化子实体时出错-它没有获取父实体的id
@Entity
@Table(name = "book")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(cascade = ALL) //The cascade is important as otherwise a new event won't be saved.
    @JoinColumn(name="book_id", referencedColumnName = "id")
    private List<BookEvent> events = new ArrayList<>();

    //Standard getter and setter for getEvents() and setEvents()
}

@Entity
public class BookEvent {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name="book_id")
    private Long bookId;

    //No getter/setter for bookId was necessary
}