JPA-where子句中的联接表列不过滤

时间:2018-12-17 17:30:01

标签: jpa spring-data-jpa jpql

我有两个表:

.exe

我需要购买历史记录为“ TRADED”的汽车。使用SQL,我可以通过以下方式做到这一点:

CREATE TABLE Car
(
    id       SERIAL PRIMARY KEY
  , model    VARCHAR(25)        NOT NULL
  , make     VARCHAR(25)        NOT NULL
);

CREATE TABLE CarHistory
(
    id SERIAL PRIMARY KEY
  , carId       INT REFERENCES car(id)       NOT NULL
  , action      VARCHAR(10)                  NOT NULL
  , actionDate  DATE                         NOT NULL
);

我有一个Car实体和CarHistory实体,如下所示:

select c.*
from Car c
join CarHistory h on h.carId=c.id
where h.action='TRADED';

我有以下@Entity @Data //lombok public class Car { @Id private Long id; private String model; private String make; @OneToMany @JoinColumn(name="carId", nullable=false) private List<CarHistory> carHistory; } @Entity @Data //lombok public class CarHistory { @Id private Long id; private String action; private Date actionDate; }

org.springframework.data.jpa.repository.Query

但是上面的public interface CarRepository extends JpaRepository<Car, Long> { @Query( "SELECT c " + "FROM Car c " + "JOIN c.carHistory as hist " + "WHERE hist.action = 'TRADED' " ) List<Car> findTradedCars(); 返回CarHistory对象。我只需要Car对象。并且它甚至返回带有CarHistory对象的Car对象,这些对象的动作属性为“ NEW”,“ BOUGHT”等!它不应该只返回具有“ TRADED”操作的CarHistory对象吗?

如何在此查询中仅获取属性为“ TRADED”的CarHistory对象?更好的是,有没有办法只获得没有CarHistory对象的Car对象(即car.getCarHistory()为null)?我真的只需要CarHistory来过滤出我想要的汽车(即交易的汽车)。

更新

我设置了@Query,现在我知道如何处理了。首先,发出与spring.jpa.properties.hibernate.show_sql=true相对应的选择语句,以获取具有“ TRADED”动作的汽车历史的汽车。然后,在@Query中返回汽车对象时:

@RestController

Jackson转换为JSON,这样做会读取Cars的CarHistory属性。然后,将为每辆汽车发出如下选择语句:

@RestController
public class CarsController {

    @NonNull
    private final CarRepository carRepo;

    @GetMapping("/traded-cars")
    public List<Cars> getTradedCars() {
        return carRepo.findTradedCars();
    }

}

值得注意的是,冬眠正在获得整个汽车历史,而不仅仅是交易汽车。

我想我可以在Car中的carHistory道具上设置select h.id, h.action, h.actionDate from CarHistory h where h.carId=? 。仍然有两个问题:

  1. 我如何才能获得仅“交易”的汽车历史记录?
  2. 更重要的是,我可以完全消除获取CarHistory对象的麻烦,这样就不必注释@JsonIgnore了吗?我什至不需要CarHistory实体。不知道我是否可以在JPQL中使用CarHistory(如果不是实体)。也许,我必须使用本地查询。

1 个答案:

答案 0 :(得分:0)

您在存储库中进行了错误的查询。 下面应该可以正常工作:

@Query("SELECT c FROM Car c " +
       "JOIN c.carHistory as hist " +
       "WHERE hist.action = 'TRADED' "
)

此外,建议将@ManyToOne放入CarHistory中进行优化:

public class Car {
    ...
    @OneToMany(mappedBy = "car")
    private List<CarHistory> carHistory;
}

public class CarHistory {
    ...
    @ManyToOne
    @JoinColumn(name = "carId")
    private Car car;
}