我使用Spring Data JPA并定义了一个原生SQL查询,旨在基于特定条件检索给定客户(KLIENCI)的单个CPC记录。然而,该查询返回CPC记录列表而不是单个记录,这不是预期的行为。
下面是SQL查询供参考:
@Query(value = "SELECT k.ID_KLIENT, k.NAZWA, k.EMAIL, \n" +
"\tc.ID_CPC , c.DATA_ROZLICZENIA, c.ID_MASZYNA, \n" +
"\tm.ID_MASZYNA, m.MODEL, m.KOLOR \n" +
"FROM KLIENCI k \n" +
"JOIN CPC c ON c.ID_KLIENT = k.ID_KLIENT \n" +
"JOIN MASZYNY m ON m.ID_KLIENT = k.ID_KLIENT AND m.ID_MASZYNA = c.ID_MASZYNA \n" +
"WHERE c.DATA_ROZLICZENIA = (\n" +
"\tSELECT MAX (c2.DATA_ROZLICZENIA)\n" +
"\tFROM CPC c2 \n" +
"\tWHERE c2.ID_KLIENT = k.ID_KLIENT AND c2.ID_MASZYNA = c.ID_MASZYNA \n" +
") AND k.ID_KLIENT = :customerId",
nativeQuery = true)
List<CustomerEntity> findCPCsForCustomer(@Param("customerId") int customerId);
字符串
下面是results在 DBeaver 中的样子:
然而,Spring创建了3个查询而不是一个,并返回指定客户的所有CPC:
Hibernate:
SELECT
k.ID_KLIENT,
k.NAZWA,
k.EMAIL,
c.ID_CPC ,
c.DATA_ROZLICZENIA,
c.ID_MASZYNA,
m.ID_MASZYNA,
m.MODEL,
m.KOLOR
FROM
KLIENCI k
JOIN
CPC c
ON c.ID_KLIENT = k.ID_KLIENT
JOIN
MASZYNY m
ON m.ID_KLIENT = k.ID_KLIENT
AND m.ID_MASZYNA = c.ID_MASZYNA
WHERE
c.DATA_ROZLICZENIA = (
SELECT
MAX (c2.DATA_ROZLICZENIA)
FROM
CPC c2
WHERE
c2.ID_KLIENT = k.ID_KLIENT
AND c2.ID_MASZYNA = c.ID_MASZYNA
)
AND k.ID_KLIENT = ?
Hibernate:
select
x1_0.id_klient,
x1_0.id_maszyna,
x1_0.kolor,
x1_0.model
from
maszyny x1_0
where
x1_0.id_klient=?
Hibernate:
select
c1_0.id_klient,
c1_0.id_cpc,
c1_0.data_rozliczenia,
c1_0.id_maszyna
from
cpc c1_0
where
c1_0.id_klient=?
型
客户类别
public class CustomerEntity {
@Id
@Column(name = "ID_KLIENT")
private int id;
@Column(name = "NAZWA")
private String name;
private String email;
@JsonManagedReference
@OneToMany(mappedBy = "customerEntity", fetch = FetchType.LAZY)
private List<XeroEntity> xeroEntityList;
@JsonManagedReference
@OneToMany(mappedBy = "customerEntity", fetch = FetchType.LAZY)
private List<CPCEntity> cpcEntityList;
}
型
Xero机器类
public class XeroEntity {
@Id
@Column(name = "ID_MASZYNA")
private int id;
private String model;
@Column(name = "KOLOR")
private String color;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_KLIENT")
private CustomerEntity customerEntity;
}
型
CPC类
public class CPCEntity {
@Id
@Column(name = "ID_CPC")
private int id;
@Column(name = "ID_MASZYNA")
private int xeroId;
@Column(name = "DATA_ROZLICZENIA")
private Date settlementDate;
@JsonBackReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_KLIENT")
private CustomerEntity customerEntity;
}
型
此外,我尝试使用JPQL来解决这个问题,但遇到了同样的问题。
我已确认数据库架构正确,预期结果是特定客户的每台计算机有一条CPC记录。但是,查询返回多条CPC记录。我不确定为什么会发生这种情况,我正在寻找有关如何修改查询或存储库方法以按预期返回一条CPC的指导。
2条答案
按热度按时间y0u0uwnf1#
您应该为该查询使用自定义实体,或者仅查询该单个CPC问题是,您正在创建一个(普通)
CustomerEntity
,这意味着当您向该实体请求其cpcEntityList
时,它将查询并返回与客户关联的所有CPC实体,这就是为什么Hibernate执行第二个和第三个查询(您的代码可能同时查询了xeroEntityList
和cpcEntityList
)。事实上,对于第一个查询,Hibernate忽略了所有没有Map到
CustomerEntity
的列:它只使用了与CustomerEntity
直接关联的列。myzjeezk2#
我同意Mark Rotteveel的观点。
延伸到他的,
我强烈建议在数据库上创建一个视图,使用与上面相同的查询(没有where子句),视图的投影接口并从Repository调用它。
但如果由于某种原因无法更改实现,则可以使用@ martyGraph
字符串
型
请注意,这仍然会执行两个查询,您只是限制了CPCEntity的响应,当XeroEntity出现类似行为时,您将面临挑战
参考文献:
1(https://stackoverflow.com/questions/54521443/when-should-i-use-entitygraph-in-spring-data-jpa)-类似堆栈溢出问题2(https://stackoverflow.com/questions/65649418/hibernate-left-join-fetch-with-on-clause-or-alternative)
我希望这能帮助