Spring Boot Jpa框架自定义查询语句返回自定义实体

开始的想法源于netcore中通过lambd查询数据库后可以直接转为实体,所以试验在java中如何实现

具体试验思路:

利用现有数据库,定义一个获取车辆的api,调用获取车辆及司机信息

1、现有车辆和司机模型

车辆表(大概列一下,实际比这多):

@Entity
@Data
@Table(name="car")
public class Car implements Serializable {

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

    /** 车牌号 */
    @ApiModelProperty("车牌号")
    @Column(name = "car_number",nullable = false)
    private String carNumber;


    /** 车辆容积 */
    @ApiModelProperty("最大载量")
    @Column(name = "car_volume",nullable = false)
    private Double carVolume;


    /** 燃料类型 */
    @ApiModelProperty("燃料类型")
    @Column(name = "fuel_type")
    private String fuelType;

    /** 百公里耗能 */
    @ApiModelProperty("百公里耗能")
    @Column(name = "energy_consumption")
    private Double energyConsumption;


    /** 车辆营运状态 */
    @ApiModelProperty("车辆状态")
    @Column(name = "car_operating_state")
    private Integer carOperatingState;

    /** 车辆状态 */
    @ApiModelProperty("车辆营运状态")
    @Column(name = "car_status",nullable = false)
    private Integer carStatus;
}

司机表

@Entity
@Data
@Table(name="driver")
public class Driver implements Serializable {

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

    /** 姓名 */
    @ApiModelProperty("姓名")
    @Column(name = "name",nullable = false)
    @NotBlank
    private String name;

    /** 性别 */
    @ApiModelProperty("性别")
    @Column(name = "sex")
    private Integer sex;

    /** 年龄 */
    @ApiModelProperty("年龄")
    @Column(name = "age")
    private Integer age;

    /** 生日 */
    @ApiModelProperty("生日")
    @Column(name = "birthday")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date birthday;

    /** 手机号 */
    @ApiModelProperty("手机号")
    @Column(name = "phone")
    private String phone;


    public void copy(Driver source){
        BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
    }
}

2、定义返回模型

最终返回

@Data
public class CarAndUnitTest {

    public CarAndUnitTest_Car<CarAndDriverTest> car;
}
@Data
public class CarAndUnitTest_Car<T> {
    public Integer all;
    public Integer working;
    public Integer alarm;
    public List<T> list;
}
@Data
public class CarAndDriverTest extends CarAndDriverTestBase {
    //车辆状态值
    private String carStatusStr;
}
@Data
public class CarAndDriverTestBase {
    private Integer id;
    //车牌号
    private String car_number;

    //最大载量
    private Double car_volume;
    //车辆状态
    private Integer car_status;
    //司机ID
    private Integer driver_id;
    //司机电话
    private String phone;
    //司机名称
    private String name;

    public CarAndDriverTestBase(Integer id,String car_number,Double car_volume,Integer car_status,Integer driver_id,String phone,String name){
        this.id=id;
        this.car_number=car_number;
        this.car_volume=car_volume;
        this.car_status=car_status;
        this.driver_id=driver_id;
        this.phone=phone;
        this.name=name;
    }

    public CarAndDriverTestBase() {
    }
}

3、定义入参模型(这个不重要)

@Data
public class QueryPara {
//    @ApiModelProperty("操作标识,1为选择机组车辆时的带条件选择,其他为不带条件的查询,可为空")
//    private int operFlag;

    @ApiModelProperty("品类名称,操作标识为1的时候不能为空,品类名称从任务单中获得")
    private String procCate;

}

4、定义服务

@ApiOperation("查询车辆和机组信息1")
    @PostMapping(value = "/getCarAndUnitTest")
    /*
        operFlag:操作标识 , proCategory:产品分类
     */
    public CarAndUnitTest getCarAndUnitTest(@RequestBody QueryPara query) {

        return carService.getCarAndUnit_1(query);
    }

5、业务实现

public CarAndUnitTest getCarAndUnit_1(QueryPara query){

        CarAndUnitTest r=new CarAndUnitTest();

        CarAndUnitTest_Car car= CarList(query);
        r.car=car;

        return  r;
    }

    //获取车
    private CarAndUnitTest_Car CarList(QueryPara query){

        CarAndUnitTest_Car r=new CarAndUnitTest_Car();
        List<CarAndDriverTest> list=allCar();
        r.list=list;
        r.all=list.size();
        r.working=0;
        r.alarm=0;
        return  r;
    }

    //所有车
    private  List<CarAndDriverTest> allCar(){
        List<CarAndDriverTest> list= new ArrayList<>();

        List<CarAndDriverTestBase> caranddriverlist=carRepository.allCarAndDriverTest();

        for(CarAndDriverTestBase obj:caranddriverlist){

            CarAndDriverTest add=new CarAndDriverTest();
            add.setId(obj.getId());
            add.setCar_status(obj.getCar_status());
            add.setCar_number(obj.getCar_number());
            add.setCar_volume(obj.getCar_volume());
            add.setDriver_id(obj.getDriver_id());

            add.setName(obj.getName());
            add.setPhone(obj.getPhone());
            add.setCarStatusStr(CarStatus.getName(obj.getCar_status()));

            list.add(add);
        }
        return list;
    }

6、数据查询

@Query(value="select new me.zhengjie.scheduling.car.domain.CarAndDriverTestBase( c.id,c.carNumber,c.carVolume,c.carStatus,c.driverId,d.phone,d.name) "+
            "FROM Car c LEFT JOIN Driver d ON c.driverId = d.id where c.flag = 1",nativeQuery = false)
    List<CarAndDriverTestBase> allCarAndDriverTest();

7、最终结果

 

记录细节,踩坑

主要是这个

@Query(value="select new me.zhengjie.scheduling.car.domain.CarAndDriverTestBase( c.id,c.carNumber,c.carVolume,c.carStatus,c.driverId,d.phone,d.name) "+
            "FROM Car c LEFT JOIN Driver d ON c.driverId = d.id where c.flag = 1",nativeQuery = false)
    List<CarAndDriverTestBase> allCarAndDriverTest();
CarAndDriverTestBase:是我们查询结果需要转换的实体
nativeQuery:false 或者nativeQuery不赋值,默认false.如果赋值true的话前面的value值是原生sql语句
new me.zhengjie.scheduling.car.domain.CarAndDriverTestBase( c.id,c.carNumber,c.carVolume,c.carStatus,c.driverId,d.phone,d.name):
我理解就是查询结果的每条数据通过调用实体的构造函数来赋值,但是又找不到实体在哪,干脆把路径补全

 注意构造函数的参数顺序

 还要注意实体的数据类型要和表实体的数据类型一致,名字可以不一样

 

 最后一点

FROM Car c LEFT JOIN Driver d ON c.driverId = d.id where c.flag = 1
其中的Car和Driver用的是表实体的name

最最重要的: 

1、查询语句中使用表实体名称

2、CarAndDriverTestBase中属性的数据类型一定要和表实体属性的数据类型一致

原文地址:https://www.cnblogs.com/fuyujian/p/13191709.html