I am trying to query for a Java Object using HQL which is performing filters based on the Object's Java Map that it has.
Essentially what I want to ask is 'give me all the error reports where mapkey1=val_x and mapkey2=val_y'
I have this object (stripped down)
@Entity
@Table(name = "error_report")
public class ErrorReport implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id", length=50)
private String id= UUID.randomUUID().toString();
@ElementCollection
@CollectionTable(name = "error_property", joinColumns = {@JoinColumn(name = "error_id", referencedColumnName = "id")})
@MapKeyColumn(name = "prop", length=50)
@Column(name = "prop_val")
@Type(type="text")
private Map<String, String> reportedProperties = new HashMap<>();
}
So I want ErrorReports based on the reportedProperties. I have set up a unit test and everything works perfectly when the reportedProperties Map has only 1 entry per ErrorReport. This is the HQL I used:
from ErrorReport as model where KEY(model.reportedProperties) = :A1 and VALUE(model.reportedProperties) = :A2
When the ErrorReport has 2 entries in the reportedProperties Map the query fails with the following error:
could not extract ResultSet caused by HsqlException: cardinality violation
When I look at the generated SQL and try and run it manually I can see it will not work, because the innter select is returning multiple results.
SELECT error_report_.id AS id1_2_, error_report_.product_url AS product_2_2_, error_report_.audit_id AS audit_id3_2_, error_report_.category_id AS
category4_2_, error_report_.error_desc AS error_de5_2_, error_report_.notifier_id AS notifier6_2_, error_report_.product_name AS
product_7_2_, error_report_.product_version AS product_8_2_, error_report_.error_time AS error_ti9_2_
FROM error_report error_report_
CROSS JOIN error_property reportedpr1_
CROSS JOIN error_property reportedpr2_
WHERE error_report_.id=reportedpr1_.error_id
AND error_report_.id=reportedpr2_.error_id
AND reportedpr1_.prop=?
AND
(SELECT reportedpr2_.prop_val FROM error_property reportedpr2_ WHERE error_report_.id=reportedpr2_.error_id)=?
Clearly there is something wrong with my HQL, but it seems to follow other examples I have found. Does anyone know what the syntax is?
I am using hibernate 5.4.9.Final
For anyone in the future, I had similar problem and solved it by applying join on the collection table combined with INDEX().
SELECT DISTINCT(model.id), model.product_url, ...
FROM ErrorReport as model
...
JOIN model.reportedProperties rProp
WHERE INDEX(rProp) = :A1 AND rProp = :A2
Here the INDEX(rProp) is the key and rProp is the value. Also DISTINCT was needed because it was returning duplicate records for me due to the map.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With