【发布时间】:2019-02-15 15:08:50
【问题描述】:
是否可以使用查询方法根据存储在附加的@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
}
问题
我有两个用例,我需要根据元数据映射中存储的信息查询实体。
- 一个用例是查找所有具有许可证的
Artworks(具有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之类的辅助标志或将艺术家移至主要实体不是一种选择。
谢谢。
【问题讨论】:
-
获取应用级别的所有过滤器?
-
这不会有效率,因为我们有几万条记录。
-
考虑JPA主要适用于CRUD。如果您的标准可以根据未来的需求而发展,其他方法可能会变得更合适(例如,用于元数据的 ElasticSearch + 用于实体的 DB)。如果您在 JPA 实体中引入“hasLicense”列,则可以解决第一个用例,并且获取速度会很快,但是在元数据中搜索匹配项 - 如果您想将其保存在数据库中,这应该是带有 FK 的单独表到主要实体。
-
谢谢,但我不打算过早优化。元数据位于带有外键的单独表中,如上所述,我想根据此信息进行查询。
标签: java spring spring-data-jpa spring-data