Java EE/JPA:应用键值表技术

Joh*_*pel 4 database jpa jakarta-ee

使用 JPA 我意识到我有动态增长的实体,即实体的属性数量可能会有所不同。知道有一些基于键值表的解决方案,我有兴趣了解有关如何将该技术应用于 JPA (JPQL) 的更多信息。

示例结构如下所示:

REF-ID       KEY         VALUE
1000         name        foo
1000         category    basic
1001         name        bar
1001         category    advanced
1001         descr       none
--------------------|------------
     PRIMARY        |
Run Code Online (Sandbox Code Playgroud)

问题是,这种表可能会大幅增长,多达数百万条记录。下一个问题是如何映射查询,例如

SELECT name, category, descr
FROM KEYSTORE 
WHERE id=1000;
Run Code Online (Sandbox Code Playgroud)

... descr 可能可用或不可用的地方

在使用 JPA 时,我是否在这里缺少任何概念来满足此要求,或者我是否必须在此处使用其他技术?性能呢?

Zie*_*elu 5

数百万条记录是数据库的正常用例。请记住在您的 ref-id 上有索引(如果它还不是主键)。您也可以通过您的 ref-id(包括 MySQL 在内的几乎所有数据库都支持)进行表分区,以提高性能,但它是数据库优化而不是 JPA 优化。

至于 JPA,您可以映射 Map<> value 如果您的属性将表示为 Strings (name, value),那么只需

class ComplexEntity {
 @ElementCollection
 @CollectionTable....
 Map<String, String> attributes;
}
....
String descr = entity.getAttributes.get("descr")
Run Code Online (Sandbox Code Playgroud)

请参阅使用 JPA 存储 Map<String,String>

或者您可以定义新的实体:属性并映射到它:

@Entity
class Attribute {
    @ID
    Long id;
    @Column(name="name")
    String name;
    @Column(name="pvalue")
    String value;
}

class ComplexEntity {
@OneToMany(cascade=CascadeType.ALL,orphanRemoval = true)
@MapKey(name="name") 
@JoinTable(name = "ATTR_TABLE")
private Map<String,Attribute> attributes;
Run Code Online (Sandbox Code Playgroud)

通过这种映射,属性映射键可以是其值的实际字段(上面的属性由 Attribute.name 值索引)。

要小心,不要调用列/对象字段 KEY、VALUE、PARAM 或任何其他潜在的 sql/jpql 关键字,因为它通常在复杂的查询中不起作用,但很难找到原因(我很难找到原因)。

至于查询,普通的 JPQL 可以工作,因此您只需抓取复杂的实体,然后从属性映射中访问感兴趣的值。或者你查询他们

SELECT a.value FROM ComplexEntity c INNER JOIN c.attributes a WHERE c.id = :id AND a.name IN :names
Run Code Online (Sandbox Code Playgroud)