【发布时间】:2017-08-17 08:09:55
【问题描述】:
案例:我有 2 个具有以下 OneToMany 关系的表:TagAbstract 1..* TagConf,其中:
-
tag_abstract_ID是一个标识许多TagConf记录的字段,这些记录是单个标签对象的历史配置, - “活动配置”被识别为具有
valid_until = NULL的配置, - 活动标签是最新配置处于活动状态的标签。
数据库架构是:
CREATE TABLE TagAbstract (
tag_abstract_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (tag_abstract_ID)
);
CREATE TABLE TagConf (
tag_conf_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
tag_abstract_ID INT UNSIGNED NOT NULL,
valid_until DATETIME,
PRIMARY KEY (tag_conf_ID),
FOREIGN KEY (tag_abstract_ID) REFERENCES TagAbstract (tag_abstract_ID)
ON DELETE CASCADE
ON UPDATE CASCADE
);
问题:是否可以使用这些 TagAbstract 记录的条件定义 Hibernate/JPA 查询(可能是 HQL),其中最后一个引用的 TagConf“处于活动状态”(如上所述)?
我卡在这里了:
public List<TagAbstract> fetchTagAbstractActive() {
//noinspection unchecked
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<TagAbstract> criteria = builder.createQuery(TagAbstract.class);
Root<TagAbstract> tagAbstractRoot = criteria.from(TagAbstract.class);
criteria.select(tagAbstractRoot);
// TODO: how to correctly define following criterion in Hibernate/JPA query?
// ---------------------------------------------------------------------
Predicate predicate = ?; // for tagConfigs[last].validUntil == NULL
// ---------------------------------------------------------------------
criteria.where(predicate);
return entityManager.createQuery(criteria).getResultList();
}
对于这个示例数据,它应该只选择记录1 和2:
record 0
tagConfigs
ref 0
tagConfId 1
tagAbstractId 1
validUntil "11-08-2017 08:11:45"
record 1
tagConfigs
ref 0
tagConfId 2
tagAbstractId 2
validUntil "11-08-2017 08:19:19"
ref 1
tagConfId 4
tagAbstractId 2
validUntil NULL
record 2
tagConfigs
ref 0
tagConfId 3
tagAbstractId 3
validUntil NULL
数据映射定义如下:
@Entity
@Table(name = "TagAbstract")
public class TagAbstract {
private static final long serialVersionUID = 1L;
@Id()
@GeneratedValue(generator = "sequence", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "sequence", allocationSize = 10)
@Column(name = "tag_abstract_ID")
private long tagAbstractId;
@OneToMany(mappedBy = "tagAbstractId", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<TagConf> tagConfigs = new ArrayList<>();
public List<TagConf> getTagConfigs() {
return tagConfigs;
}
}
@Entity
@Table(name = "TagConf")
public class TagConf {
private static final long serialVersionUID = 1L;
@Id()
@GeneratedValue(generator = "sequence", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "sequence", allocationSize = 10)
@Column(name = "tag_conf_ID")
private long tagConfId;
@Column(name = "tag_abstract_ID")
private long tagAbstractId;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = Const.DATE_TIME_PATTERN)
@Column(name = "valid_until")
private Date validUntil;
public long getTagConfId() {
return tagConfId;
}
public long getTagAbstractId() {
return tagAbstractId;
}
public Date getValidUntil() {
return validUntil;
}
}
【问题讨论】:
-
那么,您想检索所有具有活动 TagConf 的 TagAbstract 吗?那正确吗?首先修复你的映射:如果你的 OneToMany 是 mappedBy,那么 TagConf 中应该有一个 ManyToOne。 Hibernate 文档包含所有关联类型的映射示例。然后只需使用
select distinct t from TagAbstract t join t.tagConfigs tc where tc.validUntil is null。 -
也许,也许不是。我认为 OP 过度指定了查询。似乎每个标签只能激活一个标签配置,因此无需寻找最后一个。
-
@JBNizet 你是对的。我想多了。