【问题标题】:SQLNative query returning empty resultsSQLNative 查询返回空结果
【发布时间】:2019-10-13 08:47:00
【问题描述】:

我正在尝试执行需要 4 个表的查询:

    @Query(value="SELECT e.* FROM erreur e, synop sy, synop_decode sd, station st WHERE e.id_synop = sd.id_synop_decode "
            + "and sd.id_synop_decode = sy.id_synop" + " and DATE(sy.date)= :date and "
                    + "sy.id_station = st.id_station and st.id_station= :stationId", nativeQuery=true)
    public List<Erreur> recherche(@Param("date") Date date, @Param("stationId") Long stationId);

这个查询在原生 sql 中运行良好,我传递了一个现有的 stationId 和一个日期,如下所示:

SELECT e.* FROM erreur e, synop sy, synop_decode sd, station st WHERE e.id_synop = sd.id_synop_decode and sd.id_synop_decode = sy.id_synop
            and DATE(sy.date)= '2019-05-27' and sy.id_station = st.id_station and st.id_station= 60355;

此查询在 Mysql Workbench 中运行良好。

这是我用于测试目的的实际控制器:

@GetMapping("/station/{stationId}/erreurs/today")
    public List<Erreur> getTodayErreurByStationId(@PathVariable Long stationId)
    {
        List<Erreur> erreurs = new ArrayList<Erreur>();
        Optional<Station> stationOptional = stationRepository.findById(stationId);
        if(stationOptional.isPresent())
        {
            return erreurRepository.recherche(new Date(), stationId);
        }
        return null;
    }

预期的结果是我的数组列表中实际的“Ererur”对象,但 RestClient 只返回一个空数组 [],而查询在 mysql 中工作得很好,就像我上面描述的那样。

所以我的问题是:我怎样才能将此查询写成 Hql 语言,以便我可以返回正确的实体。或者我如何将我的 sql 结果映射到我的目标自定义 calss“Erreur”?

@Entity
@Getter @Setter @NoArgsConstructor
@Table(name="erreur")
public class Erreur {

    public Erreur(int section, int groupe, String info) {
        this.section = section;
        this.groupe = groupe;
        this.info = info;
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id_erreur")
    private Long id;

    @ManyToOne(cascade= {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH}, 
    fetch=FetchType.LAZY)
    @JsonIgnore
    @JoinColumn(name="id_synop")
    private SynopDecode synopDecode;

    @OneToOne
    @JoinColumn(name="id_controle")
    private Controle controle;

    @ManyToOne(cascade= {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH}, 
            fetch=FetchType.LAZY)
    @JsonIgnore
    @JoinColumn(name="id_station")
    private Station station;

    @Column(name="section")
    private int section;

    @Column(name="groupe")
    private int groupe;

    @Column(name="info")
    private String info;
}

【问题讨论】:

  • 请显示SynopDecodeSynop之间的关系
  • 你能在没有 Date 参数的情况下运行它吗?日期平等可能无法达到您的预期。

标签: sql spring-boot jpa spring-data-jpa hql


【解决方案1】:

您可以按照约定使用 jpa 方法。
假设SynopDecode 具有如下属性:

//SynopDecode class

@ManyToOne
private Synop synop;
//repository interface

List<Erreur> findByStationIdAndSynopDecodeSynopDate(Long stationId, Date date);
//or
//List<Erreur> findByStationIdAndSynopDecode_Synop_Date(Long stationId, Date date);

更新
正如 Punit Tiwan (@punit-tiwan) 所指出的,上述方法用于特定的日期时间。
您可以仅对 DATE 使用以下方法。

//repository interface

List<Erreur> findByStationIdAndSynopDecodeSynopDateBetween(Long stationId, Date startOfDate, Date endOfDate);
//or
//List<Erreur> findByStationIdAndSynopDecode_Synop_DateBetween(Long stationId, Date startOfDate, Date endOfDate);

【讨论】:

    【解决方案2】:

    如果您想直接使用 jpa 约定,则必须在不同实体之间建立关联,即两个实体如何链接。当我们定义这些关联时,spring jpa 就知道如何将方法名称或自定义查询转换为 SQL。

    您的代码需要类似于

    public class Erreur {
    ...
    @ManyToOne
    @JoinColumns//define how Erreur and SynopeDecone are linked
    private SynopDecode synopDecode;
    ...
    
    public class SynopDecode {
    ...
    @ManyToOne // or @OneToOne its not mentioned in question how these two are linked
    @JoinColumns//define how SynopDecode and Synop are linked
    private Synop synop;
    ...
    

    然后你可以写你的查询像

    @Query("select e from Erreur e LEFT JOIN e.synopDecode sy LEFT JOIN sy.synop sy WHERE DATE(sy.date) = :date AND sy.id_station = :stationId")
    List<Erreur> getByDateAndStationId(@Param("date") Date date, @Param("stationId") Long stationId)
    

    您不能使用基于方法名称的查询,因为您想使用 SQL 函数仅匹配日期的“日期”部分而不是整个时间戳。

    【讨论】:

      【解决方案3】:

      我想出了一种方法来获得与我的 SQL 查询相同的结果,使用 @Query 注释并访问对象属性,如下所示:

          @Query("from Erreur e where e.synopDecode.synop.station.id = :stationId and "
                  + "DATE(e.synopDecode.synop.date) = :date")
          public List<Erreur> recherche(@Param("date") Date date, @Param("stationId") Long stationId);
      

      我认为它解决了我的问题,感谢您的帮助

      【讨论】:

        猜你喜欢
        • 2021-03-18
        • 2021-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-04
        • 2012-10-17
        • 2017-12-19
        相关资源
        最近更新 更多