【发布时间】:2019-10-03 06:23:40
【问题描述】:
我有一个带有自定义字段的应用程序 - 用户基本上可以通过选择字段类型并为其命名来定义自定义字段。然后将自定义字段显示为实体的一部分,并将给这些字段的数据保存到我的数据库中。在大多数情况下,我已经能够以编程方式并通过正常的休眠映射(即@OneToMany 注释集合)来处理这些,而不会出现问题。但是,我目前面临一个问题。我们希望将这些自定义字段及其值用于“父”实体的实时报告。自定义字段值映射为父实体内的集合,但我需要将它们平放以进行报告。我创建了一个视图,它提供了我在 SQL 方面所需要的东西 - I followed this example to add dynamic pivoting and the resulting query is precisely how I'd like to display my information。当然不是下面的图片,但这基本上是我的输出。
视图返回完全动态的列数,每列都以自定义字段命名,并填充了该行的相关数据。
问题是我现在不知道如何使用 Hibernate 检索这些信息。
我找到了通过从 Hibernate 配置中获取 ClassMappings 来更新 PersistentClass 的文档:
Manipulating metadata at runtime
//Get the existing mapping for AgreementsGrid from Configuration
PersistentClass gridMapping = configuration.getClassMapping(AgreementsGrid.class.getName());
//Define new Column
Column column = new Column();
column.setName("ESTIMATED_COST_OVERRUNS");
column.setNullable(true);
column.setUnique(false);
gridMapping.getTable().addColumn(column);
//Wrap the column in a value
SimpleValue value = new SimpleValue();
value.setTable(gridMapping.getTable());
value.setTypeName("string");
value.addColumn(column);
//Define new property for the AgreementsGrid class
Property prop = new Property();
prop.setValue(value);
prop.setName("customField1");
prop.setNodeName(prop.getName());
gridMapping.addProperty(prop);
//Build a new session factory for the new mapping
SessionFactory sessionFactory = configuration.buildSessionFactory();
我刚刚意识到这是针对 Hibernate 3 和 4 的,甚至在 Hibernate 5 中也不可能(我使用的是 5.2.18)。
所以,我试图弄清楚如何在 Hibernate 5 中处理这个问题。我有一个映射到视图的基本实体,并且在运行时我需要能够动态地向它添加“字段”,以便我的DAO 可以动态过滤信息并处理排序/分组。
这是我的观点的实体:
@Entity
@Table(name="AGREEMENTS_GRID")
public class AgreementsGrid implements Serializable {
private static final long serialVersionUID = 1L;
private Integer entityId;
@Column(name="ENTITY_ID")
@Id
public Integer getEntityId() {
return this.entityId;
}
public void setEntityId(Integer entityId) {
this.entityId = entityId;
}
private Agreements agreement;
@ManyToOne
@JoinColumn(name = "AGREEMENT_ID", referencedColumnName = "ID", nullable = false)
public Agreements getAgreement() {
return this.agreement;
}
public void setAgreement(Agreements agreement) {
this.agreement= agreement;
}
private BigDecimal expenditure;
@Column(name = "EXPENDITURE", nullable = true, precision = 22, scale = 2)
public BigDecimal getExpenditure() {
return this.expenditure;
}
public void setExpenditure(BigDecimal expenditure) {
this.expenditure = expenditure;
}
/*
* Dynamic fields would theoretically go here and look like this,
* for a custom field of type CURRENCY named 'Estimated Cost Overruns'
*/
/*
private BigDecimal customField1;
@Column(name = "ESTIMATED_COST_OVERRUNS", nullable = true, precision = 22, scale = 2)
public BigDecimal getCustomField1() {
return this.customField1;
}
public void setCustomField1(BigDecimal customField1) {
this.customField1 = customField1;
}
*/
}
为了清楚起见,我无法在编译时映射这些字段。它们纯粹是自定义的,完全由用户定义。在运行时,我将能够知道确实存在哪些自定义字段,因此我将能够遍历它们并添加它们(正如我希望对上面看到的添加列所做的那样),但在部署之前我无法知道。自定义字段也可能随时更改。
【问题讨论】:
-
听起来你需要一个
Map<String, String>和一个连接表。 -
那到底是什么样的?