我有一个带有Map<String,String>
字段的实体,该字段是@ElementCollection
。我想选择其Map字段值与某种模式匹配的实体。但是,我在运行时遇到错误,在本例中,是H2数据库。
下面是实体:
@Entity
@Table(name = "config")
public class Config {
private String id;
private String name;
@ElementCollection
@CollectionTable(name = "setting",
joinColumns = @JoinColumn(name = "config_id", referencedColumnName = "id"))
@MapKeyColumn(name = "name", columnDefinition = "varchar(1024)")
@Column(name = "value", columnDefinition = "TEXT")
Map<String, String> settings;
}
然后,在我的JPA存储库中,我有一个方法,它可以获取具有与给定前缀匹配的设置的配置:
@Query("select config.id, config.name from Config config " +
"join config.settings setting " +
"where value(setting) like concat(:prefix, '%')")
List<List<String>> findConfigBySettingPrefix(@Param("prefix") String prefix);
这将产生来自H2的错误:
引起的原因:org.h2.jdbc.JdbcSQL数据异常:标量子查询包含多行;
JPQL生成的SQL显示value()
函数被扩展为子选择:
select config."id", config."name" from "config" config
inner join "setting" setting on config."id"=setting."config_id"
where (select setting."value" from "setting" setting where config."id"=setting."config_id") like (?||'%')
因此,当有多个匹配的设置(如预期的那样)时,这会产生一个错误,因为它们被传递到一个期望一个值的操作符中。
select config."id", config."name" from "config" config
inner join "setting" setting on config."id"=setting."config_id"
where setting."value" like (?||'%')
看起来我不能使用value()
作为where条件,或者我只是没有正确地使用它。有没有更好的方法来实现这一点?我尝试过类似的变体,它们都在启动时编译,但它们在运行时产生同样的错误:
@Query("select config.id, config.name from Config config " +
"join config.settings setting on value(setting) like concat(:prefix, '%')")
@Query("select config.id, config.name from Config config " +
"where value(config.settings) like concat(:prefix, '%')")
1条答案
按热度按时间pjngdqdw1#
这并没有准确地回答这个问题,但是它是使用JPQL的一种替代方法。