Hibernate Criteria Query 只获取特定的列
Hibernate Criteria Query to get only specific columns
我有两个 table:ReportRows 和 DataRows
Table 报告行数:
@Id
@Column(name = "ID")
private Long id;
@ManyToOne
@JoinColumn(name = "T_REPORT_CODE")
private Report report;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "T_DATA_ROWS_ID")
private DataRow dataRow;
另外还有 getter 和 setter;
Table 数据行:
@Id
@Column(name = "ID")
private Long id;
@Column(name = "VALUE_0")
private String value0;
@Column(name = "VALUE_1")
private String value1;
@Column(name = "VALUE_2")
private String value2;
...
@Column(name = "VALUE_30")
private String value30;
另外还有 getter 和 setter
ReportRows 和 DataRows 中的 Select 在列出数据时从两个 table 中获取所有列。我只需要 DataRows 中的几列(我指定它)。
我想要得到的 Select 看起来像这样:
SELECT
dataRows.value0,
dataRows.value1
from
t_report_rows this_
inner join
t_reports report_ on report_.id = this_.report_id
inner join
t_data_rows dataRows_ on dataRows_.id = this_t_data_rows_id
where report_.id = 1
这只是我写的例子。关键是我每个查询都需要不同的列。一次是 value0,value1,第二次是 value0,value2。
当我查询时,我知道我需要哪些列。
我创建这样的条件(列是 class,我从中检索列的名称):
public List<ReportRow> list(Criteria criteria, Long reportId) {
criteria.add(Restrictions.eq("report.id", reportId));
ProjectionList projectionList = Projections.projectionList();
for (Column col : columnList) {
String columnName = getColumnId(col);
projectionList.add(Projections.property(columnName));
//I also tried like this:
// projectionList.add(Projections.property(columnName), columnName);
//or like this:
//projectionList.add(Projections.property(columnName), getColumnId2(col));
//also added this line with each of above:
//criteria.setResultTransformer(Transformers.aliasToBean(ReportRow.class));
}
criteria.setProjection(projectionList);
return list(criteria);
}
方法 getColumnId 和 getColumnId2:
protected String getColumnId(Column col) {
StringBuilder b = new StringBuilder();
b.append("dataRow.value");
b.append(col.getRowIndex());
return b.toString();
}
protected String getColumnId2(Column col) {
StringBuilder b = new StringBuilder();
b.append("value");
b.append(col.getRowIndex());
return b.toString();
}
我收到错误:
org.hibernate.QueryException: 无法解析 属性: dataRow.value0
甚至可以做我想做的事吗?根据 Projection 和 table 存储列索引的列仅从 table dataRows 获取特定列?
更新 1:
我添加了自定义变压器。一切正常。这样做是为了提高 sql 的速度。现在它正在使用少量列进行查询。真的很棒。我在休眠状态下打开了 show sql 。在自定义转换器之后,它正在为每一行新查询对数据库进行操作:
where reportRowId = ?
你知道为什么吗?
自定义转换器 transformTuple 方法现在看起来像这样:
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
ReportRow row = new ReportRow();
DataRow dataRow = new DataRow();
row.setGridRow(dataRow);
for (int i = 0 ; i < aliases.length; i++) {
if ("id".equals(aliases[i])) {
row.setId((Long) tuple[i]);
} else if ("entityVersion".equals(aliases[i])) {
row.setEntityVersion((Long) tuple[i]);
} else if ("dataRowId".equals(aliases[i])) {
dataRow.setId((Long) tuple[i]);
} else if ("rowEntityVersion".equals(aliases[i])) {
dataRow.setEntityVersion((Long) tuple[i]);
} else if ("value0".equals(aliases[i])) {
dataRow.setValue0((String) tuple[i]);
} else if ("value1".equals(aliases[i])) {
dataRow.setValue1((String) tuple[i]);
}
}
return row;
}
I have problem because when I setResultTransformer it returns objects
with null variables. Example. getId() is null (I added
projectionList.add(Projections.property("id"));)
您需要指定投影的别名
projectionList.add(Projections.property("id").as("id"));
Yes, it worked. Thanks. I have one more question. If I want return
also in this query entity Report and columns value0, value1 what I
have to do?
您可以通过为其中的列指定投影来获取 Report
的一部分。您需要使用嵌套投影将 ReportRows
作为根和 Report
和 DataRow
的属性。
对于嵌套投影,您可以使用自定义转换器
session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(DlrStatus.class);
criteria.add(Restrictions.eq("userId",userId)).add(Restrictions.eq("jobId",jobId))
.add(Restrictions.eq("status", status)).setFirstResult(start).setMaxResults(max).addOrder(Order.desc("id"));
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property("mobile").as("mobile"));
projectionList.add(Projections.property("Sender").as("sender"));
projectionList.add(Projections.property("message").as("message"));
projectionList.add(Projections.property("loggedAt").as("loggedAt"));
projectionList.add(Projections.property("dlrTime").as("dlrTime"));
criteria.setProjection(projectionList);
criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<DlrStatus> list = criteria.list();
我有两个 table:ReportRows 和 DataRows
Table 报告行数:
@Id
@Column(name = "ID")
private Long id;
@ManyToOne
@JoinColumn(name = "T_REPORT_CODE")
private Report report;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "T_DATA_ROWS_ID")
private DataRow dataRow;
另外还有 getter 和 setter;
Table 数据行:
@Id
@Column(name = "ID")
private Long id;
@Column(name = "VALUE_0")
private String value0;
@Column(name = "VALUE_1")
private String value1;
@Column(name = "VALUE_2")
private String value2;
...
@Column(name = "VALUE_30")
private String value30;
另外还有 getter 和 setter
ReportRows 和 DataRows 中的Select 在列出数据时从两个 table 中获取所有列。我只需要 DataRows 中的几列(我指定它)。
我想要得到的Select 看起来像这样:
SELECT
dataRows.value0,
dataRows.value1
from
t_report_rows this_
inner join
t_reports report_ on report_.id = this_.report_id
inner join
t_data_rows dataRows_ on dataRows_.id = this_t_data_rows_id
where report_.id = 1
这只是我写的例子。关键是我每个查询都需要不同的列。一次是 value0,value1,第二次是 value0,value2。
当我查询时,我知道我需要哪些列。 我创建这样的条件(列是 class,我从中检索列的名称):
public List<ReportRow> list(Criteria criteria, Long reportId) {
criteria.add(Restrictions.eq("report.id", reportId));
ProjectionList projectionList = Projections.projectionList();
for (Column col : columnList) {
String columnName = getColumnId(col);
projectionList.add(Projections.property(columnName));
//I also tried like this:
// projectionList.add(Projections.property(columnName), columnName);
//or like this:
//projectionList.add(Projections.property(columnName), getColumnId2(col));
//also added this line with each of above:
//criteria.setResultTransformer(Transformers.aliasToBean(ReportRow.class));
}
criteria.setProjection(projectionList);
return list(criteria);
}
方法 getColumnId 和 getColumnId2:
protected String getColumnId(Column col) {
StringBuilder b = new StringBuilder();
b.append("dataRow.value");
b.append(col.getRowIndex());
return b.toString();
}
protected String getColumnId2(Column col) {
StringBuilder b = new StringBuilder();
b.append("value");
b.append(col.getRowIndex());
return b.toString();
}
我收到错误: org.hibernate.QueryException: 无法解析 属性: dataRow.value0
甚至可以做我想做的事吗?根据 Projection 和 table 存储列索引的列仅从 table dataRows 获取特定列?
更新 1:
我添加了自定义变压器。一切正常。这样做是为了提高 sql 的速度。现在它正在使用少量列进行查询。真的很棒。我在休眠状态下打开了 show sql 。在自定义转换器之后,它正在为每一行新查询对数据库进行操作:
where reportRowId = ?
你知道为什么吗?
自定义转换器 transformTuple 方法现在看起来像这样:
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
ReportRow row = new ReportRow();
DataRow dataRow = new DataRow();
row.setGridRow(dataRow);
for (int i = 0 ; i < aliases.length; i++) {
if ("id".equals(aliases[i])) {
row.setId((Long) tuple[i]);
} else if ("entityVersion".equals(aliases[i])) {
row.setEntityVersion((Long) tuple[i]);
} else if ("dataRowId".equals(aliases[i])) {
dataRow.setId((Long) tuple[i]);
} else if ("rowEntityVersion".equals(aliases[i])) {
dataRow.setEntityVersion((Long) tuple[i]);
} else if ("value0".equals(aliases[i])) {
dataRow.setValue0((String) tuple[i]);
} else if ("value1".equals(aliases[i])) {
dataRow.setValue1((String) tuple[i]);
}
}
return row;
}
I have problem because when I setResultTransformer it returns objects with null variables. Example. getId() is null (I added projectionList.add(Projections.property("id"));)
您需要指定投影的别名
projectionList.add(Projections.property("id").as("id"));
Yes, it worked. Thanks. I have one more question. If I want return also in this query entity Report and columns value0, value1 what I have to do?
您可以通过为其中的列指定投影来获取 Report
的一部分。您需要使用嵌套投影将 ReportRows
作为根和 Report
和 DataRow
的属性。
对于嵌套投影,您可以使用自定义转换器
session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(DlrStatus.class);
criteria.add(Restrictions.eq("userId",userId)).add(Restrictions.eq("jobId",jobId))
.add(Restrictions.eq("status", status)).setFirstResult(start).setMaxResults(max).addOrder(Order.desc("id"));
ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.property("mobile").as("mobile"));
projectionList.add(Projections.property("Sender").as("sender"));
projectionList.add(Projections.property("message").as("message"));
projectionList.add(Projections.property("loggedAt").as("loggedAt"));
projectionList.add(Projections.property("dlrTime").as("dlrTime"));
criteria.setProjection(projectionList);
criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<DlrStatus> list = criteria.list();