我正在使用eclipse链接开发标准JPA标准构建器查询,但是当路径导航超过两个对象时,我不知道如何优化。例如,如果我的类被称为Car,Car.objectA.objectB.objectC .. CriteriaBuilder重复加入'表
这是我的查询代码:
public List<T> getOrderedByFieldsValues(String sortField, SortOrder sortOrder, Map<String, Object> fieldValues) {
//@formatter:off
List<T> retorno = new ArrayList<T>();
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(getEntityClass());
Root<T> from = criteriaQuery.from(getEntityClass());
Predicate fullPredicate = null;
if (!fieldValues.isEmpty()) {
for (String fieldName : fieldValues.keySet()) {
if (!fieldName.contains(".")) {
if(predicateCompleto == null){
predicateCompleto = criteriaBuilder.equal(from.get(fieldName), fieldValues.get(fieldName));
}else{
predicateCompleto = criteriaBuilder.and(predicateCompleto,criteriaBuilder.equal(from.get(fieldName), fieldValues.get(fieldName)));
}
} else {
String[] campos = fieldName.split("\\.");
if (campos.length > 0) {// @formatter:off
if (campos.length <= 2) {
Join<T, T> p = from.join(campos[0]);
if(fullPredicate == null){
fullPredicate = criteriaBuilder.equal(p.get(campos[1]), fieldValues.get(fieldName));
}else{
fullPredicate = criteriaBuilder.and(fullPredicate , criteriaBuilder.equal(p.get(campos[1]), fieldValues.get(fieldName)));
}
} else {
//GENERATE DUPLICATE JOIN!!
Join<T, T>[]x = new Join[10];
//More than 10 joins is a party
for (int i = 0; i < campos.length; i++) {
if(!(i == (campos.length-1))){
if(i==0){
String valor = campos[i];
x[i] = from.join(valor);
}else{
if(i == 1){
x[i] = x[0].join(campos[i]);
}else{
//añadimos a la join anterior
x[i-1] = x[i-1].join(campos[i]);
}
}
}else{
if(fullPredicate == null){
fullPredicate = criteriaBuilder.equal(x[i-1].get(campos[i]), fieldValues.get(fieldName));
}else{
fullPredicate = criteriaBuilder.and(fullPredicate , criteriaBuilder.equal(x[i-1].get(campos[i]), fieldValues.get(fieldName)));
}
}
}
}
}
}
}
// WHERE
criteriaQuery.where(predicateCompleto);
}
if (sortField != null) {
String[] fields = sortField.split("\\.");
if (fields.length > 0) {
Path<Object> path = from.get(fields[0]);
for (int i = 1; i < fields.length; i++) {
path = path.get(fields[i]);
}
if (sortOrder == SortOrder.ASCENDING) {
criteriaQuery.orderBy(new Order[] { criteriaBuilder.asc(path) });
} else if (sortOrder == SortOrder.DESCENDING) {
criteriaQuery.orderBy(new Order[] { criteriaBuilder.desc(path) });
}
}
}
TypedQuery<T> typedQuery = getEntityManager().createQuery(criteriaQuery);
retorno = typedQuery.getResultList();
if(LOGGER.isDebugEnabled()){
LOGGER.info("QUERY - QUERY: " + typedQuery.unwrap(JpaQuery.class).getDatabaseQuery().getSQLString());
}
return retorno;
}
使用这些参数从同一个表中生成差异别名..
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("label.labelId", labelId);
params.put("collection.collectionId", collectionId);
params.put("label.format.formatId", 1L);//3 objects path
params.put("label.kindOfLabel.tipoLabelId", 1L);//3 path
结果SQL QUERY:
SELECT t1.LABEL_COLECCTIONS_ID,
t1.ACTIVE,
t1.COMMENTS,
t1.CREATED_BY,
t1.CREATION_DATE,
t1.FILE_SUPPLIER,
t1.FILE_SUPPLIER_CONTENT_TYPE,
t1.LAST_UPDATE_DATE,
t1.LAST_UPDATED_BY,
t1.REVISION,
t1.SAMPLE,
t1.COLLECTION_ID,
t1.LABEL_ID,
t1.RELATED_LABEL_COLLECTION_ID,
t1.RELATED_SEASON_ID
FROM BET_LABELS t6,
BET_COLLECTION t5,
BET_FORMATO t4,
BET_LABELS t3,
BET_TIPO_LABEL t2,
BET_LABEL_COLLECTIONS t1,
BET_LABELS t0
WHERE (((((t0.TIPO_LABEL_ID = ?)
AND (t1.COLLECTION_ID = ?))
AND (t1.LABEL_ID = ?))
AND (t3.FORMATO_ID = ?))
AND ((((((t0.LABEL_ID = t1.LABEL_ID)
AND (t3.LABEL_ID = t1.LABEL_ID))
AND (t2.TIPO_LABEL_ID = t0.TIPO_LABEL_ID))
AND (t4.FORMATO_ID = t3.FORMATO_ID))
AND (t5.COLLECTION_ID = t1.COLLECTION_ID))
AND (t6.LABEL_ID = t1.LABEL_ID)))
我正在研究解决方案,但也许有些人发现这是一个有趣的问题,任何线索都会感激不尽。 TY。