You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中按BoatBodyMaterial的matcode查询BoatCards列表的问题解决

问题:Spring JPA根据关联实体字段筛选BoatCards列表

需求

根据BoatCards实体的body_material关联字段对应的matcode值(例如matcode=2),筛选获取对应的BoatCards对象列表。

相关实体类代码

BoatBodyMaterial实体

@Entity
@Table(name = "boat_body_material")
@Data
@NoArgsConstructor
public class BoatBodyMaterial {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "matcode")
    private Integer matcode;

    @Column(name = "matname")
    private String matname;

    @Column(name = "matnote")
    private String matnote;

}

BoatCards实体

@Entity
@Table(name = "boat_cards")
@Data
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class BoatCards {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cardid")
    Long cardid;

    @Column(name = "reg_num")
    String regNum;

    @Column(name = "tiket_num")
    String tiketNum;

    @Column(name = "boat_name")
    String boatName;

    @ManyToOne
    @JoinColumn(name = "boat_type")
    BoatTypes boatType;

    @Column(name = "boat_year")
    String boatYear;

    @Column(name = "boat_vin")
    String boatVin;

    @Column(name = "parking_place")
    String parkingPlace;

    @ManyToOne
    @JoinColumn(name = "sa_category")
    SaCategory saCategory;

    @Column(name = "boat_length")
    String boatLength;

    @Column(name = "boat_width")
    String boatWidth;

    @Column(name = "boat_height")
    String boatHeight;

    @ManyToOne
    @JoinColumn(name = "body_material")
    BoatBodyMaterial bodyMaterial;

    @Column(name = "boat_payload")
    Long boatPayload;

    @Column(name = "passengers_num")
    Long passengersNum;

    @Column(name = "service_life")
    String serviceLife;

    @Column(name = "engine_num")
    Long engineNum;

    @ManyToOne
    @JoinColumn(name = "owner")
    PersonData owner;

    @ManyToOne
    @JoinColumn(name = "agent")
    PersonData agent;

    @Column(name = "note")
    String note;

}

初始实现代码

Dao层代码

public interface BoatCardsDao extends JpaRepository<BoatCards, Integer> {

    @Query(value = "SELECT * from gims.boat_body_material where matcode = 1", nativeQuery = true)
    BoatBodyMaterial findByBodyMaterial ();

    List<BoatCards> findAllByBodyMaterial(BoatBodyMaterial list);
}

Service层代码

public List<BoatCards> getAllByMaterial() {
    BoatBodyMaterial matcodeFromTable = boatCardsDao.findByBodyMaterial();
    List<BoatCards> boatCards = boatCardsDao.findAllByBodyMaterial(matcodeFromTable);
    return boatCards;
}

Controller层代码

@GetMapping(path="/get")
public List<BoatCards> get() {
    return boatCardsService.getAllByMaterial();
}

运行错误信息

2023-01-26T10:33:20.193+03:00 ERROR 20852 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Object[]] to type [by.compit.gimsshd.model.BoatBodyMaterial] for value '{1, metal, produce from metal}'] with root cause

问题解决

修改Dao层代码,利用Spring Data JPA的派生查询特性,直接通过关联实体的字段完成筛选:

public interface BoatCardsDao extends JpaRepository<BoatCards, Integer> {
    List<BoatCards> findAllByBodyMaterialMatcode(Integer bodyMaterial);
}

错误原因说明

原实现中使用原生SQL查询返回的是Object[]数组,Spring无法直接将其转换为BoatBodyMaterial实体对象。而使用JPA派生查询findAllByBodyMaterialMatcode,可以直接通过关联实体bodyMaterial的matcode字段筛选数据,无需手动查询关联实体再传递参数,既简化了代码,又避免了类型转换错误。

内容的提问来源于stack exchange,提问作者Yevgeniy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:30:52