Reputation: 185
I have an entity named certificate
@Entity
public class CertificateData {
@Id private String id;
private long expireDate;
private long createDate;
private int status;
private String subjectDN;
...
}
Many certificate can have the same subject and I want to select all certificates that have count of the field subjectId different from 3. I used this code and it worked
public List<CertificateData> findAllByRedundancy() {
Map<String, Integer> subjectDNCount = new HashMap<>();
Map<String, List<CertificateData>> subjectDNCertificates = new HashMap<>();
List<CertificateDto> certificateDataList =
this.certificaterepository
.findAll().forEach(certificateData -> {
String subject = certificateData.getSubjectDN();
if(subjectDNCount.containsKey(subject)){
subjectDNCount.put(subject, subjectDNCount.get(subject)+1);
subjectDNCertificates.get(subject).add(certificateData);
}
else{
subjectDNCount.put(subject, 1);
subjectDNCertificates.put(subject, new ArrayList<>());
subjectDNCertificates.get(subject).add(certificateData);
}
});
List<CertificateDto> result = new ArrayList<>();
subjectDNCount.forEach((s, i) -> {
if(i!=3){
result.addAll(subjectDNCertificates.get(s));
}
});
return result;
}
I tried to do the same thing using a Query-annotated Spring JPA which looks like this:
@Query("select c from CertificateData c group by c.subjectDN Having count(c) <> 3")
List<CertificateData> findAllByRedundancy();
But it doesn't return all the certificates. It returns only certificates by distincts subjectDN.
Upvotes: 0
Views: 169
Reputation: 1081
It looks like the query in your annotation is selecting groups instead of the CertificateData
records. One way to get the CertificateData
records themselves would be to use a sub-query to find the desired subjectDN
values (which is what you already have), and then have the outer query find the records with those subjectDN
values. I haven't tested this yet, but in JPQL it would be something like:
@Query(
"select c from CertificateData c where c.subjectDN in " +
"(" +
" select c.subjectDN from CertificateData c " +
" group by c.subjectDN having count(c) <> 3" +
")"
)
List<CertificateData> findAllByRedundancy();
For reference, the SQL (specifically postgres) to do this would be something like:
select * from certificate_data where subject_dn in
(
select subject_dn from certificate_data
group by subject_dn having count(*) <> 3
)
Upvotes: 1