我需要一些自定义的启用QueryDSL的查询方法,并遵循了这个SO答案。
这很好,但在升级到Spring Boot 2.1(升级Spring数据)之后,我发现QuerydslJpaRepository已经被弃用了。只需将其替换为文档告诉我要使用的QuerydslJpaPredicateExecutor,就会导致错误:
原因:java。lang.IllegalArgumentException:类[…ProjectingQueryDslJpaRepositoryImpl]的对象必须是接口org的实例。springframework。数据jpa。存储库。支持JpaRepositoryImplementation公司
。。。但是实现JpaRepositoryImplementation意味着我必须实现所有标准的CRUD方法,这显然是我不想要的。因此,如果我从EnableJpaRepositories中删除repositoryBaseClass配置,将其视为具有实现的存储库片段,它将尝试实例化该片段,即使它标记为NoRepositoryBean,也会出现错误:
原因:java.lang.IllegalArgumentException:无法为方法公共抽象创建查询java.util.可选ProjectingQueryDslJpaRepository.findOneProjecttedBy(com.querydsl.core.types.表达式,com.querydsl.core.types.谓词)!至少提供了1个参数,但查询中只有0个参数。
。。。
原因:java。lang.IllegalArgumentException:至少提供了1个参数,但查询中仅存在0个参数。
资料来源的删节版本:
@Configuration
@EnableJpaRepositories(basePackageClasses = Application.class, repositoryBaseClass = ProjectingQueryDslJpaRepositoryImpl.class)
@EnableTransactionManagement
@EnableJpaAuditing
@RequiredArgsConstructor(onConstructor = @__({@Autowired}))
public class DatabaseConfig {}
_
@NoRepositoryBean
public interface ProjectingQueryDslJpaRepository<T> extends QuerydslBinderCustomizer<EntityPath<T>>, QuerydslPredicateExecutor<T> {
@NonNull
<P> Page<P> findPageProjectedBy(@NonNull Expression<P> factoryExpression, Predicate predicate,
@NonNull Pageable pageable);
@NonNull
<P> Optional<P> findOneProjectedBy(@NonNull Expression<P> factoryExpression, @NonNull Predicate predicate);
@Override
default void customize(@NonNull QuerydslBindings bindings, @NonNull EntityPath<T> root){
bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
}
}
_
public class ProjectingQueryDslJpaRepositoryImpl<T, ID extends Serializable> extends QuerydslJpaRepository<T, ID>
implements ProjectingQueryDslJpaRepository<T> {
private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;
private final EntityPath<T> path;
private final Querydsl querydsl;
public ProjectingQueryDslJpaRepositoryImpl(@NonNull JpaEntityInformation<T, ID> entityInformation, @NonNull EntityManager entityManager) {
this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
}
public ProjectingQueryDslJpaRepositoryImpl(@NonNull JpaEntityInformation<T, ID> entityInformation, @NonNull EntityManager entityManager,
@NonNull EntityPathResolver resolver) {
super(entityInformation, entityManager, resolver);
this.path = resolver.createPath(entityInformation.getJavaType());
PathBuilder<T> builder = new PathBuilder<>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
}
@Override
public <P> Page<P> findPageProjectedBy(@NonNull Expression<P> factoryExpression, Predicate predicate,
@NonNull Pageable pageable) {
final JPQLQuery<?> countQuery = createCountQuery(predicate);
JPQLQuery<P> query = querydsl.applyPagination(pageable, createQuery(predicate).select(factoryExpression));
return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount);
}
@Override
public <P> Optional<P> findOneProjectedBy(@NonNull Expression<P> factoryExpression, @NonNull Predicate predicate) {
try {
return Optional.ofNullable(createQuery(predicate).select(factoryExpression).from(path).fetchOne());
} catch (NonUniqueResultException ex) {
throw new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
}
}
}
此测试用例具有使用querydsl运行查询的更简洁版本
https://github.com/spring-projects/spring-data-jpa/blob/master/src/test/java/org/springframework/data/jpa/repository/support/QuerydslJpaPredicateExecutorUnitTests.java
JpaEntityInformation<User, Integer> information = new JpaMetamodelEntityInformation<>(User.class,
em.getMetamodel());
SimpleJpaRepository<User, Integer> repository = new SimpleJpaRepository<>(information, em);
dave = repository.save(new User("Dave", "Matthews", "dave@matthews.com"));
carter = repository.save(new User("Carter", "Beauford", "carter@beauford.com"));
oliver = repository.save(new User("Oliver", "matthews", "oliver@matthews.com"));
adminRole = em.merge(new Role("admin"));
this.predicateExecutor = new QuerydslJpaPredicateExecutor<>(information, em, SimpleEntityPathResolver.INSTANCE, null);
BooleanExpression isCalledDave = user.firstname.eq("Dave");
BooleanExpression isBeauford = user.lastname.eq("Beauford");
List<User> result = predicateExecutor.findAll(isCalledDave.or(isBeauford));
assertThat(result).containsExactlyInAnyOrder(carter, dave);
在Spring数据JPA 2.1.6中,QueryDSLJPAPPredicateExecutor的构造函数已更改。我在这里提出了一种使用包装器的替代方法https://stackoverflow.com/a/53960209/3351474.这使得解决方案独立于Spring数据JPA的内部。必须执行三个类。
作为一个例子,我在这里使用了一个自定义的Querydsl实现,如果没有传递任何内容,则始终使用实体的creationDate
作为排序条件。在这个例子中,我假设该列存在于所有实体的某个@MepadSuperClass
中。在现实生活中使用生成的静态元数据,而不是硬编码字符串“creationDate”。
作为第一个将所有方法委托给querydsljpapredicatedexecutor的包装委托:
/**
* Customized Querydsl JPA repository to apply custom filtering and sorting logic.
*
*/
public class CustomQuerydslJpaRepositoryIml<T> implements QuerydslPredicateExecutor<T> {
private final QuerydslJpaPredicateExecutor querydslPredicateExecutor;
public CustomQuerydslJpaRepositoryIml(QuerydslJpaPredicateExecutor querydslPredicateExecutor) {
this.querydslPredicateExecutor = querydslPredicateExecutor;
}
private Sort applyDefaultOrder(Sort sort) {
if (sort.isUnsorted()) {
return Sort.by("creationDate").ascending();
}
return sort;
}
private Pageable applyDefaultOrder(Pageable pageable) {
if (pageable.getSort().isUnsorted()) {
Sort defaultSort = Sort.by(AuditableEntity_.CREATION_DATE).ascending();
pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), defaultSort);
}
return pageable;
}
@Override
public Optional<T> findOne(Predicate predicate) {
return querydslPredicateExecutor.findOne(predicate);
}
@Override
public List<T> findAll(Predicate predicate) {
return querydslPredicateExecutor.findAll(predicate);
}
@Override
public List<T> findAll(Predicate predicate, Sort sort) {
return querydslPredicateExecutor.findAll(predicate, applyDefaultOrder(sort));
}
@Override
public List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
return querydslPredicateExecutor.findAll(predicate, orders);
}
@Override
public List<T> findAll(OrderSpecifier<?>... orders) {
return querydslPredicateExecutor.findAll(orders);
}
@Override
public Page<T> findAll(Predicate predicate, Pageable pageable) {
return querydslPredicateExecutor.findAll(predicate, applyDefaultOrder(pageable));
}
@Override
public long count(Predicate predicate) {
return querydslPredicateExecutor.count(predicate);
}
@Override
public boolean exists(Predicate predicate) {
return querydslPredicateExecutor.exists(predicate);
}
}
接下来,CustomJpaRepositoryFactory执行魔术并提供Querydsl包装类,而不是默认的包装类。默认值作为参数传递并包装。
/**
* Custom JpaRepositoryFactory allowing to support a custom QuerydslJpaRepository.
*
*/
public class CustomJpaRepositoryFactory extends JpaRepositoryFactory {
/**
* Creates a new {@link JpaRepositoryFactory}.
*
* @param entityManager must not be {@literal null}
*/
public CustomJpaRepositoryFactory(EntityManager entityManager) {
super(entityManager);
}
@Override
protected RepositoryComposition.RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
final RepositoryComposition.RepositoryFragments[] modifiedFragments = {RepositoryComposition.RepositoryFragments.empty()};
RepositoryComposition.RepositoryFragments fragments = super.getRepositoryFragments(metadata);
// because QuerydslJpaPredicateExecutor is using som internal classes only a wrapper can be used.
fragments.stream().forEach(
f -> {
if (f.getImplementation().isPresent() &&
QuerydslJpaPredicateExecutor.class.isAssignableFrom(f.getImplementation().get().getClass())) {
modifiedFragments[0] = modifiedFragments[0].append(RepositoryFragment.implemented(
new CustomQuerydslJpaRepositoryIml((QuerydslJpaPredicateExecutor) f.getImplementation().get())));
} else {
modifiedFragments[0].append(f);
}
}
);
return modifiedFragments[0];
}
}
最后是CustomJpaRepositoryFactoryBean。这必须在Spring Boot应用程序中注册,以使Spring知道从何处获取存储库实现,例如:
@SpringBootApplication
@EnableJpaRepositories(basePackages = "your.package",
repositoryFactoryBeanClass = CustomJpaRepositoryFactoryBean.class)
...
现在上课:
public class CustomJpaRepositoryFactoryBean<T extends Repository<S, I>, S, I> extends JpaRepositoryFactoryBean<T, S, I> {
/**
* Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface.
*
* @param repositoryInterface must not be {@literal null}.
*/
public CustomJpaRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new CustomJpaRepositoryFactory(entityManager);
}
}
对于Spring Boot 2.1.1,以下解决方案可能会对您有所帮助。关键是扩展JpaRepositoryFactory并重写方法getRepositoryFragments(RepositoryMetadata元数据)。在这种方法中,您可以为任何自定义存储库提供基本(或更具体的片段)实现,每个扩展存储库都应该使用这些实现。
让我给你举个例子:
QueryableReadRepository:
@NoRepositoryBean
public interface QueryableReadRepository<T> extends Repository<T, String> {
List<T> findAll(Predicate predicate);
List<T> findAll(Sort sort);
List<T> findAll(Predicate predicate, Sort sort);
List<T> findAll(OrderSpecifier<?>... orders);
List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Page<T> findAll(Pageable page);
Page<T> findAll(Predicate predicate, Pageable page);
Optional<T> findOne(Predicate predicate);
boolean exists(Predicate predicate);
}
以下界面组合了不同的存储库。
数据存储库:
@NoRepositoryBean
public interface DataRepository<T>
extends CrudRepository<T, String>, QueryableReadRepository<T> {
}
现在,您的特定域Repo可以从DataRepository扩展:
@Repository
public interface UserRepository extends DataRepository<UserEntity> {
}
QueryableReadRepositoryImpl:
@Transactional
public class QueryableReadRepositoryImpl<T> extends QuerydslJpaPredicateExecutor<T>
implements QueryableReadRepository<T> {
private static final EntityPathResolver resolver = SimpleEntityPathResolver.INSTANCE;
private final EntityPath<T> path;
private final PathBuilder<T> builder;
private final Querydsl querydsl;
public QueryableReadRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager, resolver, null);
this.path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
this.querydsl = new Querydsl(entityManager, builder);
}
@Override
public Optional<T> findOne(Predicate predicate) {
return super.findOne(predicate);
}
@Override
public List<T> findAll(OrderSpecifier<?>... orders) {
return super.findAll(orders);
}
@Override
public List<T> findAll(Predicate predicate, Sort sort) {
return executeSorted(createQuery(predicate).select(path), sort);
}
@Override
public Page<T> findAll(Predicate predicate, Pageable pageable) {
return super.findAll(predicate, pageable);
}
@Override
public List<T> findAll(Predicate predicate) {
return super.findAll(predicate);
}
public List<T> findAll(Sort sort) {
return executeSorted(createQuery().select(path), sort);
}
@Override
public Page<T> findAll(Pageable pageable) {
final JPQLQuery<?> countQuery = createCountQuery();
JPQLQuery<T> query = querydsl.applyPagination(pageable, createQuery().select(path));
return PageableExecutionUtils.getPage(
query.distinct().fetch(),
pageable,
countQuery::fetchCount);
}
private List<T> executeSorted(JPQLQuery<T> query, Sort sort) {
return querydsl.applySorting(sort, query).distinct().fetch();
}
}
CustomRepositoryFactoryBean:
public class CustomRepositoryFactoryBean<T extends Repository<S, I>, S, I>
extends JpaRepositoryFactoryBean<T, S, I> {
public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new CustomRepositoryFactory(entityManager);
}
CustomRepositoryFactory:
public class CustomRepositoryFactory extends JpaRepositoryFactory {
private final EntityManager entityManager;
public CustomRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
@Override
protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) {
RepositoryFragments fragments = super.getRepositoryFragments(metadata);
if (QueryableReadRepository.class.isAssignableFrom(
metadata.getRepositoryInterface())) {
JpaEntityInformation<?, Serializable> entityInformation =
getEntityInformation(metadata.getDomainType());
Object queryableFragment = getTargetRepositoryViaReflection(
QueryableReadRepositoryImpl.class, entityInformation, entityManager);
fragments = fragments.append(RepositoryFragment.implemented(queryableFragment));
}
return fragments;
}
主要类别:
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class App {
}
这样做的好处是,您只为自定义repo提供一个(片段)实现。基本存储库实现仍然是Spring的默认实现。该示例提供了一个新的repo,但您也可以在CustomRepositoryFactory中重写QueryDSLPediateExecutor的默认实现
在iOS7中,现在是不推荐的。现在如何将UIFont对象传递到替换方法中?
问题内容: 我发现这段代码的工作方式是,我可以以编程方式创建richfaces下拉菜单。但是不推荐使用某些代码。谁能告诉我要放什么而不是不赞成使用的电话? 谢谢 不推荐使用的代码行是: 问题答案: javadocs明确指出: 不推荐使用 。通过调用getExpressionFactory()然后 ExpressionFactory.createMethodExpression(javax.el.E
问题内容: 我已经继承了代码 @已弃用,并显示为“ 没有RequestConfig的类文档,我不知道应该使用哪种方法来替换and 。 问题答案: 您正在将apache HttpClient 4.3库与apache HttpClient 4.2代码一起使用。 请注意,在您的情况下,getParams()和ConnRoutePNames不是唯一不推荐使用的方法。DefaultHttpClient类本身
我的错误日志中出现了以下错误:woocommerce_product_tax_class从3.0.0版开始就不推荐使用了!改用woocommerce_product_get_tax_class。 我有以下功能来显示不同的用户角色不同的税务类。我可以直接将“woocommerce_product_tax_class”更改为“woocommerce_product_get_tax_class”吗?
问题内容: 我的Java代码中有一些不推荐使用的方法,如果有人可以在这里指导我,我将不胜感激。我有一个私有的Date变量: 在我的方法中,我声明了: 其他方法(例如和)也已弃用。 我知道我必须使用。如何在这里使用新代码?所有的setHours,getMinutes等都用上划线显示。 问题答案: 如果我正确理解了您的问题,这应该可以: 如果没有,您可以向我们显示要替换日期代码的完整方法吗? 编辑:这
问题内容: 这个问题已经在这里有了答案 : 用preg_replace_callback替换preg_replace()e修饰符 (3个答案) 4年前关闭。 上面的代码在升级到PHP 5.5后给出了弃用警告: 不推荐使用 :preg_replace():不推荐使用/ e修饰符,而应使用preg_replace_callback 如何用替换代码? 问题答案: 您可以使用匿名函数将匹配项传递给函数: