我有两个表:
.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=?
。仍然有两个问题:
@JsonIgnore
了吗?我什至不需要CarHistory实体。不知道我是否可以在JPQL中使用CarHistory(如果不是实体)。也许,我必须使用本地查询。答案 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;
}