java 将有效SQL查询转换为有效HQL时出错

vnzz0bqm  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(291)

我正在运行一个SpringBoot Java应用程序,它目前使用的是hibernate-core 6.1.7.Final。我有一个有效的SQL查询,它提供了我需要的结果,我需要将其转换为HQL,以便我的应用程序可以运行查询并返回相同的结果。然而,我在应用程序启动时不断收到错误。我有多个不同的错误,而试图修复HQL,当前错误的基础上,当前版本的代码如下所示:
java.lang.IllegalArgumentException: Component at index 0 has no alias, but alias is required
下面是给出正确结果的工作SQL查询:

SELECT PARENT.* 
      , CHILD1.* 
    FROM [dbo].[PARENT] PARENT 
  INNER JOIN [dbo].[CHILD] CHILD1 
      ON CHILD1.ParentId = PARENT.id 
  INNER JOIN ( 
      SELECT parentId, MAX(effectivetimestamp) as MaxEff, Max([createdtimestamp]) as MaxCre 
        FROM [dbo].[CHILD] as CHILD2
        WHERE CHILD2.effectivetimestamp < Cast(Getutcdate() at time zone 'UTC' at time zone 'GMT Standard Time' AS DATETIME2) 
        GROUP BY parentId 
      ) CHILD2 
    ON CHILD2.parentId = CHILD1.parentId 
    AND CHILD2.MaxEff = CHILD1.effectiveTimestamp 
    AND CHILD2.MaxCre = CHILD1.createdTimestamp

dbo.PARENT与dbo. CHILD具有一对多关系。dbo.CHILD具有effectiveTimestamp列,并且此查询将返回具有当前活动Child的所有Parents(每个Parent的最新effectiveTimestamp值不是未来日期)。
下面是Parent和Child的Java实体类:

@Entity
@Table(name = "PARENT")
public class Parent {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;

    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @Fetch(value = FetchMode.SUBSELECT)
    @JsonManagedReference
    private List<Child> child;

    public List<Child> getChild() {
        return child;
    }

    public void setChild(List<Child> child) {
        this.child = child;
    }

}
@Entity
@Table(name = "CHILD")
public class Child {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;
    
    @ManyToOne
    @JoinColumn(name = "parentId")
    @JsonBackReference
    private Parent parent;
    
    @Column(name = "effectiveTimestamp", nullable = false)
    private LocalDateTime effectiveTimestamp;
    
    @Column(name = "createdTimestamp", nullable = false)
    private LocalDateTime createdTimestamp;
    

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }

    public LocalDateTime getEffectiveTimestamp() {
        return effectiveTimestamp;
    }

    public void setEffectiveTimestamp(LocalDateTime effectiveTimestamp) {
        this.effectiveTimestamp = effectiveTimestamp;
    }

    public LocalDateTime getCreatedTimestamp() {
        return createdTimestamp;
    }

    public void setCreatedTimestamp(LocalDateTime createdTimestamp) {
        this.createdTimestamp = createdTimestamp;
    }

}

这是我目前对本机hibernate查询的尝试,目前失败了。我希望它返回表中的所有父对象,仅将当前活动的子对象连接到父对象。

@Query(value = "SELECT PARENT, CHILD1 FROM Parent PARENT "
              + " INNER JOIN Child CHILD1 "
              + "   ON CHILD1.parent.id = PARENT.id "
              + "   INNER JOIN "
              + "  ( SELECT CHILD1.parent.id, MAX(CHILD1.effectiveTimestamp) as MaxEff, MAX(CHILD1.createdTimestamp) as MaxCre "
              + "  FROM Child as CHILD2 "
              + "     WHERE CHILD1.effectiveTimestamp <= :currentTimestamp "
              + "     GROUP BY CHILD1.parent.id "
              + "     ) CHILD2 "
              + "   ON CHILD2.parent.id = CHILD1.parent.id "
              + "   AND CHILD2.MaxEff = CHILD1.effectiveTimestamp "
              + "   AND CHILD2.MaxCre = CHILD1.createdTimestamp " )
      Optional<List<Parent>> getAllActiveChildByParent(@Param("currentTimestamp") LocalDateTime currentTimestamp);

任何帮助将不胜感激。

更新根据Andrey B的评论。Panfilov下面我已经添加了失踪的别名,可以在下面看到。

@Query(value = "SELECT PARENT, CHILD1 FROM Parent PARENT "
              + " INNER JOIN Child CHILD1 "
              + "   ON CHILD1.parent.id = PARENT.id "
              + "   INNER JOIN "
              + "  ( SELECT CHILD1.parent.id as NEWALIAS, MAX(CHILD1.effectiveTimestamp) as MaxEff, MAX(CHILD1.createdTimestamp) as MaxCre "
              + "  FROM Child as CHILD2 "
              + "     WHERE CHILD1.effectiveTimestamp <= :currentTimestamp "
              + "     GROUP BY CHILD1.parent.id "
              + "     ) CHILD2 "
              + "   ON CHILD2.parent.id = CHILD1.parent.id "
              + "   AND CHILD2.MaxEff = CHILD1.effectiveTimestamp "
              + "   AND CHILD2.MaxCre = CHILD1.createdTimestamp " )
      Optional<List<Parent>> getAllActiveChildByParent(@Param("currentTimestamp") LocalDateTime currentTimestamp);

但是我现在得到这个错误:

Caused by: org.hibernate.query.SemanticException: Could not resolve attribute 'parent' of 'java.lang.Object[]'

通过分解hibernate查询,我相信错误来自第二个内部连接,但我看不到该部分中的什么导致了错误。

c9qzyr3d

c9qzyr3d1#

使用我在Andrey B的评论后面添加的别名。Panfilov,我不得不在我的第二个内部连接中使用该别名来修复“无法解析属性”错误。下面的hibernate查询现在可以工作了。

@Query(value = "SELECT PARENT, CHILD1 FROM Parent PARENT "
              + " INNER JOIN Child CHILD1 "
              + "   ON CHILD1.parent.id = PARENT.id "
              + "   INNER JOIN "
              + "  ( SELECT CHILD1.parent.id as NEWALIAS, MAX(CHILD1.effectiveTimestamp) as MaxEff, MAX(CHILD1.createdTimestamp) as MaxCre "
              + "  FROM Child as CHILD2 "
              + "     WHERE CHILD1.effectiveTimestamp <= :currentTimestamp "
              + "     GROUP BY CHILD1.parent.id "
              + "     ) CHILD2 "
              + "   ON NEWALIAS = CHILD2.parent.id "
              + "   AND CHILD2.MaxEff = CHILD1.effectiveTimestamp "
              + "   AND CHILD2.MaxCre = CHILD1.createdTimestamp " )
      Optional<List<Parent>> getAllActiveChildByParent(@Param("currentTimestamp") LocalDateTime currentTimestamp);

相关问题