Java 使用Spring数据JpaRepositories按ElementCollections中的值查询实体
是否可以使用查询方法根据附加的Java 使用Spring数据JpaRepositories按ElementCollections中的值查询实体,java,spring,spring-data-jpa,spring-data,Java,Spring,Spring Data Jpa,Spring Data,是否可以使用查询方法根据附加的@ElementCollection中存储的值查询JPA存储库中的实体 设置 我的Spring Boot 2/Spring 5应用程序有一个实体(Artwork),可以附加任意元数据。 元数据是通过使用@ElementCollection和@CollectionTable的简单键值映射实现的,因为元数据只是纯文本键/值对,不存在于其实体的范围之外 实体如下所示: @Entity @Table(name = "artwork") public class Artwor
@ElementCollection
中存储的值查询JPA存储库中的实体
设置
我的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
}
一般来说,查询似乎是可能的。但我在StackOverflow上找到的大多数答案都是关于,而不是在地图上
所以我的问题是
如何使用查询方法根据附加的@ElementCollection
中存储的值查询JPA存储库中的实体?或者我需要使用JPA的一对多映射在对象级别转换这种关系吗
更新
- 因为我们在artist表中有数万条记录,所以我希望在数据库级别进行筛选,而不是在应用程序中进行筛选李>
- 按元数据查询将变得很常见,因此引入辅助标志(如
)或将艺术家移动到主实体不是一个选项李>hasLicense
谢谢 JPA2.0允许使用
KEY()
和VALUE()
引用JPQL中基于地图的@ElementCollection
中的键和值
通常,您可以使用它们来解决您的问题。但是,如中所述,对于VALUES()
…,Hibernate似乎是一种奇怪的行为。。。。。。幸运的是,它做到了
无论如何,您的问题可以通过以下@Query
(假设您使用的是Hibernate。如果您使用其他提供程序,您可以尝试VALUES()
):
要查找特定艺术家的所有艺术品,请执行以下操作:
artworkRepository.findArtworkByMetadata("artist" , "someName");
在应用程序级别上提取所有的过滤器?因为我们有数万个记录,这将是不有效的。如果您的标准可以根据未来的需求发展,其他方法可能会更合适(例如,ElasticSearch for metdata+DB for entities)。如果您在JPA实体中引入“hasLicense”列,那么第一个用例就可以解决,并且抓取会很快,但是在元数据中搜索匹配项-如果您想将其保留在DB中,这应该是一个单独的表,其中FK是主实体。谢谢,但我不打算过早优化。元数据位于一个单独的表中,表中有一个外键,如上所述,我希望根据此信息进行查询。谢谢,这看起来很有希望。我假设,
VALUES()
在中是可选的(KEY(meta)=:name和meta=:value)
?目前我遇到了一些延迟初始化问题,但是生成的sql看起来不错。在(KEY(meta)=:name和meta=:value)
中,我没有使用VALUES()
,因为正如我提到的,它在Hibernate中有问题。
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");