版本: 0.7.0
JRepository或KJRepository中没有提供findAll(Predicate predicate)
和findOne(Predicate predicate)
这样的方法
类似QueryDsl中的QuerydslPredicateExecutor
:
public interface QuerydslPredicateExecutor<T> {
Optional<T> findOne(Predicate predicate);
Iterable<T> findAll(Predicate predicate);
}
是否可以考虑实现这样的方法呢?
我尝试实现这样的方法时, 碰到了一个问题
SqlClient没有createQuery(Class<?> entityClass)
这样能够基于实体类型创建查询的方法, 只有通过Table<E>
创建查询的方法, 因此必须通过repository提供Table
对象才可能实现.
例如:
public interface BaseJimmerRepository<E, ID> extends JRepository<E, ID> {
<T extends TableProxy<E>> T table();
default List<E> findAll(Predicate predicate) {
return sql().createQuery(table()).where(predicate).select(table()).execute();
}
}
实体的Repository:
public interface DeviceJimmerRepository extends BaseJimmerRepository<Device,Long> {
@Override default DeviceTable table() {
return DeviceTable.$;
}
}
Repository中能内置实现这种方法吗, 亦或者提供方便检索实体对应的Table
的方法呢?
------------------------------------编辑
我找到了JRepositoryImpl中的一个方法org.babyfish.jimmer.spring.repository.support.JRepositoryImpl#createQuery
private ConfigurableRootQuery<?, E> createQuery(Fetcher<E> fetcher, TypedProp.Scalar<?, ?>[] sortedProps) {
MutableRootQueryImpl<Table<E>> query =
new MutableRootQueryImpl<>(sqlClient, immutableType, ExecutionPurpose.QUERY, false);
Table<E> table = query.getTable();
for (TypedProp.Scalar<?, ?> sortedProp : sortedProps) {
if (!sortedProp.unwrap().getDeclaringType().isAssignableFrom(immutableType)) {
throw new IllegalArgumentException(
"The sorted field \"" +
sortedProp +
"\" does not belong to the type \"" +
immutableType +
"\" or its super types"
);
}
PropExpression<?> expr = table.get(sortedProp.unwrap().getName());
Order astOrder;
if (sortedProp.isDesc()) {
astOrder = expr.desc();
} else {
astOrder = expr.asc();
}
if (sortedProp.isNullsFirst()) {
astOrder = astOrder.nullsFirst();
}
if (sortedProp.isNullsLast()) {
astOrder = astOrder.nullsLast();
}
query.orderBy(astOrder);
}
query.freeze();
return query.select(fetcher != null ? table.fetch(fetcher) : table);
}
也许我知道该怎么自己实现了
----------------------------编辑
出问题了
jdk版本: 17
jimmer版本: 0.7.0
异常栈:
java.lang.IllegalArgumentException: Cannot resolve the root table xxx.xxx.xxx.Device
at org.babyfish.jimmer.sql.ast.impl.AstContext.resolveRootTable(AstContext.java:85) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.table.spi.AbstractTypedTable.__resolve(AbstractTypedTable.java:334) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.table.TableProxies.resolve(TableProxies.java:142) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.PropExpressionImpl.accept(PropExpressionImpl.java:109) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.ComparisonPredicate.accept(ComparisonPredicate.java:26) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.AbstractMutableQueryImpl.accept(AbstractMutableQueryImpl.java:191) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.AbstractConfigurableTypedQueryImpl.accept(AbstractConfigurableTypedQueryImpl.java:53) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.ConfigurableRootQueryImpl.accept(ConfigurableRootQueryImpl.java:21) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.ConfigurableRootQueryImpl.preExecute(ConfigurableRootQueryImpl.java:201) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.ConfigurableRootQueryImpl.executeImpl(ConfigurableRootQueryImpl.java:155) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.spring.repository.SpringConnectionManager.execute(SpringConnectionManager.java:22) ~[jimmer-spring-boot-starter-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.ConfigurableRootQueryImpl.execute(ConfigurableRootQueryImpl.java:135) ~[jimmer-sql-0.7.0.jar:na]
at org.babyfish.jimmer.sql.ast.impl.query.ConfigurableRootQueryImpl.execute(ConfigurableRootQueryImpl.java:21) ~[jimmer-sql-0.7.0.jar:na]
at xxx.xxx.xxx.xxx..xxx.BaseJimmerRepository.findAll(BaseJimmerRepository.java:69) ~[classes/:na]
其中BaseJimmerRepository
中的代码如下:
@NoRepositoryBean
public interface BaseJimmerRepository<E>
extends JRepository<E, Long> {
private ConfigurableRootQuery<?, E> createQuery(
Predicate predicate, Fetcher<E> fetcher, TypedProp.Scalar<?, ?>[] sortedProps) {
var immutableType = type();
MutableRootQueryImpl<Table<E>> query =
new MutableRootQueryImpl<>(sql(), immutableType, ExecutionPurpose.QUERY, false);
Table<E> table = query.getTable();
for (TypedProp.Scalar<?, ?> sortedProp : sortedProps) {
if (!sortedProp.unwrap().getDeclaringType().isAssignableFrom(immutableType)) {
throw new IllegalArgumentException(
"The sorted field \""
+ sortedProp
+ "\" does not belong to the type \""
+ immutableType
+ "\" or its super types");
}
PropExpression<?> expr = table.get(sortedProp.unwrap().getName());
Order astOrder;
if (sortedProp.isDesc()) {
astOrder = expr.desc();
} else {
astOrder = expr.asc();
}
if (sortedProp.isNullsFirst()) {
astOrder = astOrder.nullsFirst();
}
if (sortedProp.isNullsLast()) {
astOrder = astOrder.nullsLast();
}
query.orderBy(astOrder);
}
var tableMutableRootQuery = query.where(predicate);
query.freeze();
return tableMutableRootQuery.select(fetcher != null ? table.fetch(fetcher) : table);
}
default List<E> findAll(Predicate predicate) {
return createQuery(predicate).execute(); // 调用execute报错
}
controller调用的代码
@GetMapping("test")
public List<xxx.xxx.xxx.xxx.Device> test() {
return deviceJimmerRepository.findAll(DeviceTable.$.mac().eq("0011AABBCC00"));
}
看起来是MutableRootQueryImpl
的getTable
返回的Table
不能用来组成条件.
所以还是回到最开始的问题: 是否考虑由Repository提供通过Predicate的查询, 或可以通过实体类检索Table对象的方法, 如果不考虑的话, 我就只能采用实体的Repository提供table的方式了.