我正在尝试执行一个需要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;
}
答案 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);
我认为它可以解决我的问题,谢谢您的帮助