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

我有以下实体,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 加载导演,然后创建新电影并最后保存它。这会导致两次访问数据库:第一次检索导演,第二次保存电影。


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


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


九州编程
浏览 176回答 3
3回答

函数式编程

没有办法告诉代码Person它需要与您的新Movie. 因此,您确实需要执行查询并手动进行关联。只有当您的端点Person在创建Movie. 然后您可以简单地执行 2 个保存操作或使用 aCascadeType=ALL进行单个保存操作。如果您能够更改请求参数,那么接收完整Person对象而不是接受directorId. 这样你就可以建立关联movie.director = director;。小心这种类似的方法:如果接收到的Person对象没有存储在您的数据库中,您将收到一个异常。也许您可以为您的Directors. 例如,如果您将所有 Director 都保存在 Redis 中,则可以搜索Director与接收到的对应directorId的然后执行关联。当然,您仍然需要进行第二次操作,但它可能比查询数据库便宜得多。

尚方宝剑之说

这会很丑,但你的请求中有 personId,所以你可以用你的长 personId 映射你的电影class Movie {    @Id Long id;    @Column String name;    @ManyToOne Person director;    @Column(name="PERSON_ID")    long personId;}在你的控制器中movie.setPersonId(request.directorId);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java