繁体   English   中英

使用Spring Data JPA处理POST请求中的关系

[英]Handling relations in POST requests with Spring Data JPA

我有以下实体,每个实体都有一个CrudRepository

@Entity
class Movie {
    @Id Long id;
    @Column String name;
    @ManyToOne Person director;
}

@Entity
class Person {
    @Id Long id;
    @Column String name;
}

我的控制器看起来像这样:

@RestController
@RequestMapping("/movies")
class MovieController {

    private MovieRepository movies = ...;
    private PersonRepository people = ...;

    @PostMapping
    public Movie create(@RequestBody MovieRequest request) {
        // Get the director
        Person director = people.findById(request.directorId);

        // Create the new movie
        Movie movie = new Movie();
        movie.name = request.name;
        movie.director = director;

       // Save the new movie
       return movies.save(movie);
    }
}

class MovieRequest {
    String name;
    Long directorId
}

如您所见, create方法首先按其id加载director,然后创建新影片并最终保存。 这导致两次访问数据库:第一次检索导演,第二次保存电影。

在这种情况下,这不是一个大问题,但可能存在一个有很多关系的实体,这意味着可能会进行大量查询以实现单个插入。

问题 :我想在单个数据库操作中保存新电影。 有没有办法避免初始人查询? 有没有更好的方法来处理这样的案件?

有没有办法告诉代码至极Person ,它需要涉及到你的新Movie 因此,您确实需要执行查询并手动进行关联。

只有当您的端点在创建Movie的同时创建Person时,才有可能实现替代方案。 然后,您可以简单地执行2个保存操作或使用CascadeType=ALL进行单个保存操作。


如果你能够改变你的请求参数,可能是一个不错的选择接收一个完整的Person的对象,而不是一个accpeting的directorId 这样你就可以制作关联movie.director = director;

小心这种方法:如果收到的Person对象没有存储在你的数据库中,你将得到一个例外。


也许你可以为你的Directors创建一个缓存。 例如,如果您将所有董事保存在Redis中,则可以搜索与收到的directorId相对应的Director然后执行关联。

当然,你仍然需要进行第二次操作,但它可能比查询数据库便宜。

这将是丑陋的,但你在请求中有personId,所以你可以用你长的人映射你的电影

class Movie {
    @Id Long id;
    @Column String name;
    @ManyToOne Person director;

    @Column(name="PERSON_ID")
    long personId;
}

在你的控制器中

movie.setPersonId(request.directorId);

我不认为您的MOVIE表包含“ DIRECTOR_NAME ”列(假设您遵循第二规范化规则)。 它应该只是 DIRECTOR_ID

因此,您可以完全跳过在场景中加载控制器名称(前提是directId与请求的查询参数一起发送)。

既然你(应该有)之间的外键约束 Movie.DIRECTOR_IDDIRECTOR.ID ,它会寻找任何约束违例之后,如果你想插入任何DIRECTOR_ID不存在。 所以你不必担心。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM