SQLNative查询返回空结果

时间:2019-05-27 19:52:59

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

我正在尝试执行一个需要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结果映射到目标自定义校准“ 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;
}

3 个答案:

答案 0 :(得分:0)

您可以按照约定使用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);

答案 1 :(得分:0)

如果您想直接使用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函数仅匹配日期的“日期”部分而不匹配整个时间戳。

答案 2 :(得分:0)

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

    @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);

我认为它可以解决我的问题,谢谢您的帮助