【问题标题】:JPA crud repository queryJPA crud 存储库查询
【发布时间】:2019-10-25 15:22:07
【问题描述】:

我正在尝试学习 Spring,但遇到了 JPA 存储库查询问题 我有 2 个相互之间存在双向关系的类:

public class MovieGenre {
   // other fields

   @ManyToMany(mappedBy = "genres")
   @JsonBackReference
   private Set<Movie> movies = new HashSet<>();
   // ...
}

public class Movie {
// id and other fields

   @ManyToMany(fetch = FetchType.EAGER)
   @JoinTable(
           name = "movie_movie_genre",
           joinColumns = @JoinColumn(name = "movie_id"),
           inverseJoinColumns = @JoinColumn(name = "movie_genre_id"))
   @JsonManagedReference
   private Set<MovieGenre> genres = new HashSet<>();

我想创建控制器,以便能够获取包含其中一种类型的所有电影的 json。 我试图让 jpa 查询为我做这件事。

public interface MovieRepository extends CrudRepository<Movie, Long> {

   Stream<Movie> getMoviesByGenresIsLike(String genreName);
}

这个不行

为了给 Idead 我试图达到的目标是正常的 sql 查询(它在 h2 控制台中工作)

SELECT * FROM MOVIE m 
INNER JOIN movie_movie_genre mmg ON m.movie_id = mmg.movie_id
INNER JOIN movie_genre mg ON mmg.movie_genre_id = mg.genre_id
WHERE genre_name = 'action';

我正在尝试编写这样的自定义查询

@Query(value = "SELECT * FROM MOVIE m \n" +
       "INNER JOIN movie_movie_genre mmg ON m.movie_id = mmg.movie_id\n" +
       "INNER JOIN movie_genre mg ON mmg.movie_genre_id = mg.genre_id\n" +
       "WHERE genre_name = ?1;", nativeQuery = true)
Optional<Movie> getMoviesByGenres(@Param("name") String name);

这一切都导致

2019-10-25 17:07:42.405 ERROR 831 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]
    : Servlet.service() for servlet [dispatcherServlet] in context with path [] 
threw exception [Request processing failed; 
nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: 
JPA-style positional param was not an integral ordinal; 
nested exception is java.lang.IllegalArgumentException: org.hibernate.QueryException: 
JPA-style positional param was not an integral ordinal] with root cause
  • 有什么方法可以按类型获取电影列表?
  • 如果无法进行 jpa 查询,如何编写正确的自定义查询?

  • 编辑: - 我将查询更改为“SELECT m FROM Movie m INNER JOIN m.genres g WHERE g.genreName = ?1”(如下面的答案中所建议的) -- 另一个问题是控制器中缺少@Transactional 注释。

【问题讨论】:

    标签: java spring jpa


    【解决方案1】:

    尝试从使用原生查询切换到 jpql 概念:

    "SELECT m FROM Movie m INNER JOIN m.genres g WHERE g.genreName = ?1"
    

    或者你可以创建一个MovieGenreRepository 并创建一个类似的方法:

    Stream<MovieGenre> findByGenreNameLike(String genreName);
    

    【讨论】:

      【解决方案2】:

      首先你必须很好地映射你的实体,如果字段的名称与你的 SQL 查询完全相同,那么它将是这样的:

      @Repository
      public interface MovieRepository extends CrudRepository<Movie, Long> {
      
          @Query(value = "SELECT m FROM Movie m INNER JOIN m.genres g ON m.movie_id = g.movie_id WHERE g.genreName = :name")
          Movie getMoviesByGenres(@Param("name") String name);
      }
      

      不要忘记添加@Repository 注解,因为我们必须始终遵循休眠标准。

      【讨论】:

      • 感谢您的回复。在接口上使用@Repository 有什么意义?
      • 它为所有用@Repository注解的bean激活持久性异常转换,让JPA持久性提供者抛出的异常被转换成Spring的DataAccessException层次结构。这意味着该类中抛出的所有未经检查的异常都将转换为 DataAccessException。 docs.spring.io/spring-data/jpa/docs/current/reference/html/…
      猜你喜欢
      • 2021-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      • 2021-04-16
      • 1970-01-01
      • 2015-10-04
      相关资源
      最近更新 更多