Java EE/JPA:应用键值 table 技术
Java EE/JPA: Applying key-value table techniques
使用 JPA 我意识到我有动态增长的实体,即属性的数量可能因实体而异。知道有一些基于键值 tables 的解决方案,我很想了解有关如何将该技术应用于 JPA (JPQL) 的更多信息。
示例结构如下:
REF-ID KEY VALUE
1000 name foo
1000 category basic
1001 name bar
1001 category advanced
1001 descr none
--------------------|------------
PRIMARY |
已知的问题是这种 table 可能会急剧增长,达到数百万条记录。
下一个问题是如何映射查询,比如
SELECT name, category, descr
FROM KEYSTORE
WHERE id=1000;
... 描述可能可用或不可用
在使用 JPA 时我是否缺少任何概念来满足此要求,或者我是否必须在此处使用其他技术?性能怎么样?
数百万条记录是数据库的正常用例。
请记住在您的 ref-id 上有索引(如果它还不是主键)。您也可以通过您的 ref-id 进行 table 分区(包括 MySQL 在内的几乎所有数据库都支持),以提高性能,但这是数据库优化而不是 JPA 优化。
至于JPA,可以映射Map<>值
如果您的属性将表示为字符串(名称,值),则只需
class ComplexEntity {
@ElementCollection
@CollectionTable....
Map<String, String> attributes;
}
....
String descr = entity.getAttributes.get("descr")
见Storing a Map<String,String> using JPA
或者您可以定义新的实体:属性并映射到它:
@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;
使用这种映射,属性映射键可以是其值的实际字段(以上属性由 Attribute.name 值索引)。
小心,不要调用 columns/object 字段 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
使用 JPA 我意识到我有动态增长的实体,即属性的数量可能因实体而异。知道有一些基于键值 tables 的解决方案,我很想了解有关如何将该技术应用于 JPA (JPQL) 的更多信息。
示例结构如下:
REF-ID KEY VALUE
1000 name foo
1000 category basic
1001 name bar
1001 category advanced
1001 descr none
--------------------|------------
PRIMARY |
已知的问题是这种 table 可能会急剧增长,达到数百万条记录。 下一个问题是如何映射查询,比如
SELECT name, category, descr
FROM KEYSTORE
WHERE id=1000;
... 描述可能可用或不可用
在使用 JPA 时我是否缺少任何概念来满足此要求,或者我是否必须在此处使用其他技术?性能怎么样?
数百万条记录是数据库的正常用例。 请记住在您的 ref-id 上有索引(如果它还不是主键)。您也可以通过您的 ref-id 进行 table 分区(包括 MySQL 在内的几乎所有数据库都支持),以提高性能,但这是数据库优化而不是 JPA 优化。
至于JPA,可以映射Map<>值 如果您的属性将表示为字符串(名称,值),则只需
class ComplexEntity {
@ElementCollection
@CollectionTable....
Map<String, String> attributes;
}
....
String descr = entity.getAttributes.get("descr")
见Storing a Map<String,String> using JPA
或者您可以定义新的实体:属性并映射到它:
@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;
使用这种映射,属性映射键可以是其值的实际字段(以上属性由 Attribute.name 值索引)。
小心,不要调用 columns/object 字段 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