我在我的代码中使用Criteria Query。它始终触发select * from ...
相反,我想从我的查询中忽略一个列(字段),因为该字段有大量以字节存储的数据。这导致了性能问题。
任何人都可以为此提出想法吗?
部分更新
我在查询中添加了一个投影,它创建了一个类似...的查询
select
this_.TEMPLATE_ID as y0_,
this_.TEMPLATE_NAME as y1_,
this_.CREATE_DATE as y2_,
this_.UPDATE_DATE as y3_,
this_.STATUS_CODE as y4_,
this_.USER_ID as y5_,
this_.UPDATED_BY as y6_,
this_.CATEGORY_ID as y7_,
this_.PRACTICE_ID as y8_
from
templates this_
inner join
user user1_
on this_.USER_ID=user1_.USER_ID
inner join
template_categories category2_
on this_.CATEGORY_ID=category2_.CATEGORY_ID
where
y4_=?
and y8_=?
and y5_ in (
?, ?
)
order by
y1_ asc limit ?
现在问题就像... Unknown column 'y4_' in 'where clause'
和y8_相同的错误,y5_表示所有关闭的地方都给出了错误。
我将其修改为像...一样查询
select
this_.TEMPLATE_ID as y0_,
this_.TEMPLATE_NAME as y1_,
this_.CREATE_DATE as y2_,
this_.UPDATE_DATE as y3_,
this_.STATUS_CODE as y4_,
this_.USER_ID as y5_,
this_.UPDATED_BY as y6_,
this_.CATEGORY_ID as y7_,
this_.PRACTICE_ID as y8_
from
templates this_
inner join
user user1_
on this_.USER_ID=user1_.USER_ID
inner join
template_categories category2_
on this_.CATEGORY_ID=category2_.CATEGORY_ID
where
this_.STATUS_CODE=1
and this_.PRACTICE_ID=1
and this_.USER_ID in (
1, 2
)
order by
y1_ asc limit ?
它有效。但我不知道如何在HQL中修改它?
答案 0 :(得分:92)
使用Projections指定要返回的列。
示例强>
SQL查询
SELECT user.id, user.name FROM user;
Hibernate Alternative
Criteria cr = session.createCriteria(User.class)
.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("Name"), "Name"))
.setResultTransformer(Transformers.aliasToBean(User.class));
List<User> list = cr.list();
答案 1 :(得分:1)
您可以将JPQL以及JPA Criteria API用于任何类型的DTO投影(仅将选定的列映射到DTO类)。查看下面的代码段,这些代码段显示如何有选择地选择各种列而不是 选择所有列。这些示例还显示了如何从中选择各种列 连接多列。我希望这有帮助 。
JPQL代码:
String dtoProjection = "new com.katariasoft.technologies.jpaHibernate.college.data.dto.InstructorDto"
+ "(i.id, i.name, i.fatherName, i.address, id.proofNo, "
+ " v.vehicleNumber, v.vechicleType, s.name, s.fatherName, "
+ " si.name, sv.vehicleNumber , svd.name) ";
List<InstructorDto> instructors = queryExecutor.fetchListForJpqlQuery(
"select " + dtoProjection + " from Instructor i " + " join i.idProof id " + " join i.vehicles v "
+ " join i.students s " + " join s.instructors si " + " join s.vehicles sv "
+ " join sv.documents svd " + " where i.id > :id and svd.name in (:names) "
+ " order by i.id , id.proofNo , v.vehicleNumber , si.name , sv.vehicleNumber , svd.name ",
CollectionUtils.mapOf("id", 2, "names", Arrays.asList("1", "2")), InstructorDto.class);
if (Objects.nonNull(instructors))
instructors.forEach(i -> i.setName("Latest Update"));
DataPrinters.listDataPrinter.accept(instructors);
JPA Criteria API代码:
@Test
public void fetchFullDataWithCriteria() {
CriteriaBuilder cb = criteriaUtils.criteriaBuilder();
CriteriaQuery<InstructorDto> cq = cb.createQuery(InstructorDto.class);
// prepare from expressions
Root<Instructor> root = cq.from(Instructor.class);
Join<Instructor, IdProof> insIdProofJoin = root.join(Instructor_.idProof);
Join<Instructor, Vehicle> insVehicleJoin = root.join(Instructor_.vehicles);
Join<Instructor, Student> insStudentJoin = root.join(Instructor_.students);
Join<Student, Instructor> studentInsJoin = insStudentJoin.join(Student_.instructors);
Join<Student, Vehicle> studentVehicleJoin = insStudentJoin.join(Student_.vehicles);
Join<Vehicle, Document> vehicleDocumentJoin = studentVehicleJoin.join(Vehicle_.documents);
// prepare select expressions.
CompoundSelection<InstructorDto> selection = cb.construct(InstructorDto.class, root.get(Instructor_.id),
root.get(Instructor_.name), root.get(Instructor_.fatherName), root.get(Instructor_.address),
insIdProofJoin.get(IdProof_.proofNo), insVehicleJoin.get(Vehicle_.vehicleNumber),
insVehicleJoin.get(Vehicle_.vechicleType), insStudentJoin.get(Student_.name),
insStudentJoin.get(Student_.fatherName), studentInsJoin.get(Instructor_.name),
studentVehicleJoin.get(Vehicle_.vehicleNumber), vehicleDocumentJoin.get(Document_.name));
// prepare where expressions.
Predicate instructorIdGreaterThan = cb.greaterThan(root.get(Instructor_.id), 2);
Predicate documentNameIn = cb.in(vehicleDocumentJoin.get(Document_.name)).value("1").value("2");
Predicate where = cb.and(instructorIdGreaterThan, documentNameIn);
// prepare orderBy expressions.
List<Order> orderBy = Arrays.asList(cb.asc(root.get(Instructor_.id)),
cb.asc(insIdProofJoin.get(IdProof_.proofNo)), cb.asc(insVehicleJoin.get(Vehicle_.vehicleNumber)),
cb.asc(studentInsJoin.get(Instructor_.name)), cb.asc(studentVehicleJoin.get(Vehicle_.vehicleNumber)),
cb.asc(vehicleDocumentJoin.get(Document_.name)));
// prepare query
cq.select(selection).where(where).orderBy(orderBy);
DataPrinters.listDataPrinter.accept(queryExecutor.fetchListForCriteriaQuery(cq));
}
答案 2 :(得分:1)
我喜欢这种方法,因为它既简单又干净:
String getCompaniesIdAndName = " select "
+ " c.id as id, "
+ " c.name as name "
+ " from Company c ";
@Query(value = getCompaniesWithoutAccount)
Set<CompanyIdAndName> findAllIdAndName();
public static interface CompanyIdAndName extends DTO {
Integer getId();
String getName();
}
答案 3 :(得分:0)
您可以根据此类映射另一个实体(您应该使用实体名称来区分这两个),第二个实体将是dto(不要忘记dto has design issues)。 你应该将第二个定义为readonly并给它一个好名字,以便明确这不是一个普通的实体。 顺便说一下,只选择几列称为投影,所以google将更容易。
替代方案 - 您可以使用所需的字段列表创建命名查询(将它们放在选择中)或使用带投影的条件
答案 4 :(得分:0)
您可以为此使用multiselect
功能。
CriteriaBuilder cb=session.getCriteriaBuilder();
CriteriaQuery<Object[]> cquery=cb.createQuery(Object[].class);
Root<Car> root=cquery.from(User.class);
cquery.multiselect(root.get("id"),root.get("Name"));
Query<Object[]> q=session.createQuery(cquery);
List<Object[]> list=q.getResultList();
System.out.println("id Name");
for (Object[] objects : list) {
System.out.println(objects[0]+" "+objects[1]);
}
冬眠5支持此功能。createCriteria
在冬眠的其他版本中已弃用。因此,您可以改用criteria builder
。