在Spring Boot应用程序中,我们使用queryDSL来访问数据库。应用程序应从一个表中打印出与(用户输入的受抚养人)搜索参数相匹配的所有项目。
示例:
所以我们必须动态创建where子句。
我们使用类似的实体类
package example;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "location")
public class LocationEntity {
@Id
@GeneratedValue
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "name", nullable = false)
private String name;
public LocationEntity() {
// -
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
类似的查询类
package example;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.StringPath;
public class QLocationEntity extends EntityPathBase<LocationEntity> {
private static final long serialVersionUID = 1L;
public static final QLocationEntity DEFAULT = new QLocationEntity("loc_1");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final StringPath name = createString("name");
public QLocationEntity(String tableAlias) {
super(LocationEntity.class, tableAlias);
}
}
类似的存储库类
package example;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface LocationRepository extends JpaRepository<LocationEntity, Long>,
/* needed for query DSL. */
QuerydslPredicateExecutor<LocationEntity> {
/*
* We don't need custom methods.
*/
}
和类似的小帮手类
package example;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
@Service
public class LocationRepositoryHelper {
protected final Log LOG = LogFactory.getLog(getClass());
@Autowired
private LocationRepository repository;
public Sort sort = new Sort(Sort.Direction.ASC, "name");
public Iterable<LocationEntity> findEntities(String paramLocation, boolean autocomplete)
throws RequestParameterInvalideException {
Predicate p = generatePredicate(paramLocation, autocomplete);
if (p != null) {
return repository.findAll(p, sort);
} else {
return repository.findAll(sort);
}
}
BooleanExpression generatePredicate(String location, boolean autocomplete) {
if ("".equals(location.trim())) {
return null;
} else if (autocomplete) {
return QLocationEntity.DEFAULT.name.startsWith(location);
} else {
return QLocationEntity.DEFAULT.name.eq(location);
}
}
}
(此示例远没有我们实际的应用程序代码复杂,但是足以说明我们的问题。)
我们的应用程序要求帮助程序类提供列表,而弹簧靴应该通过巫毒来完成其余的工作。
当我们使用oracle数据库作为rdbms时,一切都很好。当我们使用ignite时,只要我们不尝试使用“自动完成”功能就可以了。
当我们尝试“自动完成搜索字符串”时,我们收到一个IgniteException,内容为:不支持的查询:locationen0_.name,如?1 ESCAPE'!'
我们记录了以下sql字符串:
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name like ? escape '!' order by locationen0_.name asc
我们假设“?”必须替换为“ Ber%”,因此完全限定的sql语句应为:
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name like 'Ber%' escape '!' order by locationen0_.name asc;
我们在Oracle DB(12. *)和Ignite(2.7)的SQL控制台中手动运行了该语句。在Oracle上一切正常,Ignite仍宣布我们将出现语法错误/不支持的查询。 所以我们在Ignite上尝试了一些替代方案...
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name = 'Berlin' order by locationen0_.name asc;
=> all fine, but doesn't return what we want.
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name like 'Berlin' order by locationen0_.name asc;
=> all fine, but still doesn't return what we want.
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name = 'Ber%' order by locationen0_.name asc;
=> still all fine and would return what we want.
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name = 'Berlin' escape '!' order by locationen0_.name asc;
=> all fine (woot??), but wouldn't return what we want.
select locationen0_.id as id1_0_, locationen0_.name as name2_0_ from my_location locationen0_ where locationen0_.name = 'Ber%' escape '!' order by locationen0_.name asc;
=> (the original statement) unsupported query, but is what queryDSL (supposedly) generates and what should return what we want.
我们的第一个结论是:
经过几个小时的分析,我们现在知道“是什么原因导致了问题”,但我们根本不知道为什么这是一个问题。 queryDSL框架(版本4.2.1)附加了经过硬编码的转义关键字,因此我们不知道如何抑制它。 切换到另一个框架可能是一个选择,尽管我们希望避免重构。 转储框架并“通过字符串连接构建语句”是可行的,但对于有效的代码则不可行。
所以我们的问题是: 是否有人使用queryDSL和Ignite,并且没有此问题? 如果是这样,您是否以与我们完全不同的方式使用queryDSL? (我们是否以“不被使用”的方式使用queryDSL?) 还是您知道Ignite的配置选项可以解决该问题? 其他人有提示吗?
答案 0 :(得分:0)
我已经研究了来源,事实证明Ignite明确禁止ESCAPE。我们检查是否提供了ESCAPE并指出错误。
我认为您可以针对Apache Ignite JIRA提出问题。