Java 基于子实体属性的JPA查询

Java 基于子实体属性的JPA查询,java,spring-boot,jpa,jql,Java,Spring Boot,Jpa,Jql,我有4个实体,屏幕,放映和电影。我想写两个查询 查找屏幕是否存在给定屏幕名称给定MultiPlexId。 (假设id为1的多路复用器有4个屏幕,奥迪-1、奥迪-2、奥迪-3和奥迪-4,查询应该能够找到id为1的多路复用器中是否存在奥迪-2) 查找在给定日期运行给定电影的所有多路复用器(放映有屏幕、电影和日期的参考) 我的实体 电影:- @Entity public class Movie { @Id @GeneratedValue(strategy = GenerationTy

我有4个实体,屏幕,放映和电影。我想写两个查询

  • 查找屏幕是否存在给定屏幕名称给定MultiPlexId。 (假设id为1的多路复用器有4个屏幕,奥迪-1、奥迪-2、奥迪-3和奥迪-4,查询应该能够找到id为1的多路复用器中是否存在奥迪-2)

  • 查找在给定日期运行给定电影的所有多路复用器(放映有屏幕、电影和日期的参考)

  • 我的实体

    电影:-

    @Entity
    public class Movie {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
    
        private String title;
    
        private double rating;
    }
    
    多路复用:-

    @Entity
    public class Multiplex {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
    
        private String name;
    
        @OneToMany(mappedBy = "multiplex", cascade = CascadeType.ALL)
        private List<Screen> screens;
    }
    
    筛选:-

    @Entity
    public class Screening {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
    
        @OneToOne
        private Screen screen;
    
        @OneToOne
        private Movie movie;
    
        private LocalDate date;
    
        private LocalTime time;
    
        private float pricePerSeat;
    }
    
    对于我尝试的第一个查询

    @Query("SELECT m FROM Multiplex m Where m.id = :mId and m.screens.name = :screenName")
        public Optional<Multiplex> findScreenByName(@Param("mId") long id, @Param("screenName") String name);
    
    我很确定我需要使用连接,但我在广告中搜索了一下,却找不出答案。
    非常感谢您的帮助。

    m.screens
    不是
    屏幕
    字段,而是
    列表
    。所以表达式
    m.screens.name:=screenName
    是错误的

    试试这个

    (一)

    @Query(“从多路复用m中选择m,屏幕s,其中m.id=s.Multiplex.id和m.id=:mId和s.name=:screenName”)
    公共可选findByMultiplexIdAndScreenName(@Param(“mId”)长id,@Param(“screenName”)字符串名);
    
    (二)

    @Query(“从多路复用m中选择不同的m,其中m.id=s.screen.Multiplex.id和s.movie=:movie和s.date=:date”)
    公共列表findAllByMovieAndDate(@Param(“movie”)movie movie,@Param(“date”)LocalDate日期);
    

    @Query(“从屏幕s中选择不同的s.screen.multiplex,其中s.movie=:movie和s.date=:date”)
    公共列表findAllByMovieAndDate(@Param(“movie”)movie movie,@Param(“date”)LocalDate日期);
    

    如果决定将FetchTypes更改为Lazy

    m,则使用最后一个选项可以得到异常。screens
    不是
    屏幕
    字段,而是
    列表
    。所以表达式
    m.screens.name:=screenName
    是错误的

    试试这个

    (一)

    @Query(“从多路复用m中选择m,屏幕s,其中m.id=s.Multiplex.id和m.id=:mId和s.name=:screenName”)
    公共可选findByMultiplexIdAndScreenName(@Param(“mId”)长id,@Param(“screenName”)字符串名);
    
    (二)

    @Query(“从多路复用m中选择不同的m,其中m.id=s.screen.Multiplex.id和s.movie=:movie和s.date=:date”)
    公共列表findAllByMovieAndDate(@Param(“movie”)movie movie,@Param(“date”)LocalDate日期);
    

    @Query(“从屏幕s中选择不同的s.screen.multiplex,其中s.movie=:movie和s.date=:date”)
    公共列表findAllByMovieAndDate(@Param(“movie”)movie movie,@Param(“date”)LocalDate日期);
    

    如果决定将FetchTypes更改为Lazy,使用最后一个,您可以得到异常

    查询二如何,我如何加入筛选和多路复用?@Lucifer Morningstar您也可以这样做。我添加了第二个查询示例顺便说一句,我想在放映实体中电影和银幕需要@manytone查询二如何,我如何加入放映和多路复用?@Lucifer Morningstar你也可以这样做。我已经添加了第二个查询示例顺便说一句,我认为在放映实体中,电影和屏幕需要@ManyToOne
    @Query("SELECT m FROM Multiplex m Where m.id = :mId and m.screens.name = :screenName")
        public Optional<Multiplex> findScreenByName(@Param("mId") long id, @Param("screenName") String name);
    
    Caused by: org.hibernate.QueryException: illegal attempt to dereference collection [multiplex0_.id.screens] with element property reference [id]
        at org.hibernate.hql.internal.ast.tree.DotNode$1.buildIllegalCollectionDereferenceException(DotNode.java:58)
        at org.hibernate.hql.internal.ast.tree.DotNode.checkLhsIsNotCollection(DotNode.java:629)
        at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:242)
        at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1045)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1290)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4706)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4174)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2138)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2066)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:815)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:609)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:271)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:191)
        ... 77 common frames omitted
    
    @Query("select m from Multiplex m, Screen s where m.id=s.multiplex.id and m.id =:mId and s.name =:screenName")
        public Optional<Multiplex> findByMultiplexIdAndScreenName(@Param("mId") long id, @Param("screenName") String name);
    
    @Query("select distinct m from Multiplex m, Screening s where m.id=s.screen.multiplex.id and s.movie=:movie and s.date =:date")
            public List<Multiplex> findAllByMovieAndDate(@Param("movie") Movie movie, @Param("date") LocalDate date);
    
    @Query("select distinct s.screen.multiplex from Screening s where s.movie=:movie and s.date =:date")
                public List<Multiplex> findAllByMovieAndDate(@Param("movie") Movie movie, @Param("date") LocalDate date);