是否可以使用查询方法根据附加在@ElementCollection
中的值来查询JpaRepository中的实体?
设置
我的Spring Boot 2 / Spring 5应用程序有一个实体(Artwork
),可以将任意元数据附加到该实体。
元数据是使用@ElementCollection
和@CollectionTable
通过简单的键值映射实现的,因为元数据只是纯文本键/值对,并不存在于其实体范围之外。
该实体看起来像这样:
@Entity
@Table(name = "artwork")
public class Artwork implements Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
// more propperties
@ElementCollection
@MapKeyColumn(name = "name")
@Column(name = "value")
@CollectionTable(name = "artwork_metadata", joinColumns = @JoinColumn(name = "artwork_id"))
private Map<String, String> metadata = new HashMap<>();
// more code
}
问题
我有两个用例,其中我需要根据元数据图中存储的信息来查询实体。
Artwork
(无论值列中有metadata.name = license
)metadata.name = artist
和metadata.value = someName
的键/值对)我曾尝试使用下划线表示手动属性路径;但我的数据类型是地图,而不是具有字段name
/ value
的对象。
public interface ArtworkRepository extends JpaRepository<Artwork, Long> {
List<Artwork> findAllByReleaseDateAfter(Instant after);
// Not working
List<Artwork> findAllByMetadata_NameAndMetadata_value
一般来说,查询是可能的。但是我在StackOverflow上找到的大多数答案都是关于searching in Lists,而不是地图。
我的问题是
如何使用查询方法基于附件@ElementCollection
中存储的值查询JpaRepository中的实体?还是我需要使用JPA的一对多映射在对象级别转换这种关系。
更新
hasLicense
之类的帮助器标记,或者将艺术家移至主要实体。 谢谢。
答案 0 :(得分:2)
JPA 2.0允许使用KEY()
和VALUE()
来引用JPQL中基于地图的@ElementCollection
中的键和值。
通常,您可以使用它们来解决问题。但是,如this中所述,对于VALUES()
来说,休眠似乎是一种奇怪的行为……幸运的是,它具有workaround。
无论如何,可以通过以下@Query
解决问题(假设您正在使用Hibernate。如果使用其他提供程序,则可以尝试VALUES()
)。 :
public interface ArtworkRepository extends JpaRepository<Artwork, Long> {
@Query(value = "select a from Artwork a join a.metadata meta where (KEY(meta) = :name)")
public List<Artwork> findArtworkByMetadata(@Param("name") String name);
@Query(value = "select a from Artwork a join a.metadata meta where (KEY(meta) = :name and meta = :value)")
public List<Artwork> findArtworkByMetadata(@Param("name") String name, @Param("value") String value);
}
要查找所有具有许可的艺术品:
artworkRepository.findArtworkByMetadata("license");
要查找特定艺术家的所有艺术品:
artworkRepository.findArtworkByMetadata("artist" , "someName");