首页 > 解决方案 > 无法在 Intellij IDEA 的 Spring Boot 中添加一个等于和哈希码的实体?

问题描述

我有一个关于在电影实体中添加更多类型的问题。因为我在更新类型方面有更新电影的问题,如新值所示。这就是为什么我在所有以流派、导演和电影命名的实体中使用equals和。hashcode

我曾经把它建在Intellij IDEA

但是,当我调用getMovieByIdand时,我只显示第一种流派,同时又添加了一个流派updateMovieById

我该如何解决这个问题?

这是我的项目链接:项目链接

这是我的流派、电影和导演的 equals 和 hashcode 方法。我只添加流派的一个。

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Genre)) return false;
        Genre genre = (Genre) o;
        return Objects.equals(getId(), genre.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }

这是我的测试类,如下所示。

@Test
    void createMovie() throws ParseException {
        Movie movie = new Movie();
        movie.setName("Movie A");
        movie.setRating(7.5);

        Director movieDirector = new Director();
        movieDirector.setName("Director 1");
        movie.setDirector(movieDirector);

        Genre genreFirst = new Genre();
        genreFirst.setName("Adventure");
        genreFirst.setMovie(movie);

        Genre genreSecond = new Genre();
        genreSecond.setName("Action");
        genreSecond.setMovie(movie);

        movie.addGenre(genreFirst);
        movie.addGenre(genreSecond);

        Movie createdMovie = movieService.save(movie);
        System.out.println("createdMovie Id : " + createdMovie.getId());

        assertThat(createdMovie.getId()).isGreaterThan(0);
    }

编辑

这是我的 updateMovieById,如下所示。

@Test
    void updateMovieById() throws ParseException {

    createMovie();

    Long id = 1L;
    Movie movie = movieService.findById(id).get();

    movie.setName("Movie B");
    movie.setRating(7.5);

    Director movieDirector = new Director();
    movieDirector.setName("Director 2");
    movie.setDirector(movieDirector);

    LocalDate now = Utils.formatDate(LocalDate.of(2019, Month.JANUARY, 1));
    movie.setCreatedAt(now);

    Genre genreFirst = new Genre();
    genreFirst.setName("Historical");
    genreFirst.setMovie(movie);

    Genre genreSecond = new Genre();
    genreSecond.setName("Horror");
    genreSecond.setMovie(movie);

    movie.addGenre(genreFirst);
    movie.addGenre(genreSecond);

    Movie updatedMovie = movieService.update(id,movie);


    assertThat(updatedMovie.getId()).isGreaterThan(0);
}

当我更新电影时,类型如下所示。我该如何解决这个问题?

MovieService | update | Movie Genre : Adventure
MovieService | update | Movie Genre : Action
MovieService | update | Movie Genre : Historical
MovieService | update | Movie Genre : Horror

标签: javaspring-bootjpa

解决方案


问题是您将Genrea 存储在SetMovie中。

 @OneToMany(mappedBy="movie",cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
    private Set<Genre> genres = new HashSet<>();

只要Genre实例没有保存在数据库中,它们id仍然是null,所以 equals/hashcode 实现会将它们视为相等,并且其中只有 1 个保留在Set(aSet不允许重复)中。

如果要保留 id 由数据库分配的事实,则需要像这样实现 equals 和 hashcode:

@Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Genre gene = (Genre) o;
        return id != null &&
                id.equals(genre.id);
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }

有关更多信息,请参阅如何使用 JPA 实体标识符实现 equals 和 hashCode,或参阅Equals 和 hashcode implementation 注意事项以获得更广泛的讨论。

另一种实现是使用早期主键生成,您首先生成主键并手动将其传递给构造函数。


推荐阅读