自己手写一个BaseRepository过程中遇到的问题

先看看BaseRepository:

@NoRepositoryBean
public interface BaseRepository<DOMAIN, ID> extends JpaRepository<DOMAIN, ID> {

    @NonNull
    List<DOMAIN> findAllByIdIn(@NonNull Collection<ID> ids, @NonNull Sort sort);

    @NonNull
    Page<DOMAIN> findAllByIdIn(@NonNull Collection<ID> ids, @NonNull Pageable pageable);

    long deleteByIdIn(@NonNull Collection<ID> ids);

}

关于findAllByIdIn方法的具体实现:

if (entityInformation.hasCompositeId()) {
    List<DOMAIN> results = new ArrayList<>();
    ids.forEach(id -> super.findById(id).ifPresent(results::add));
    return results;
}

ByIdsSpecification<DOMAIN> specification = new ByIdsSpecification<>(entityInformation);
TypedQuery<DOMAIN> query = super.getQuery(specification, sort);
return query.setParameter(specification.parameter, ids).getResultList();

如上代码所示,为何有复合主键时可以直接一个一个findById? 然后没有复合主键时,下面的代码又是什么意思?

你可以看看底层SQL日志。复合ID和普通ID的SQL有什么不同。
我猜测一下:
如果是复合ID,就遍历ID参数。挨个的 findById检索。
如果不是复合ID的话,就直接用 WHERE ID IN (..) 这种方式来检索,省事儿。不用遍历。

1 个赞

懂了,万分感谢!!! :kissing_heart:

前辈,就是自己实现基类的时候,这几个类还没有完全搞懂。您能简单的给我讲一下他们的作用嘛?
1、Root
2、CriteriaQuery
3、CriteriaBuilder
4、Path
5、ParameterExpression
6、JpaEntityInformation

比如说下面这段代码:

private static final class ByIdsSpecification<T> implements Specification<T> {
    private static final long serialVersionUID = 1L;
    private final JpaEntityInformation<T, ?> entityInformation;
    @Nullable
    ParameterExpression<Collection> parameter;

    ByIdsSpecification(JpaEntityInformation<T, ?> entityInformation) {
        this.entityInformation = entityInformation;
    }

    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Path<?> path = root.get(this.entityInformation.getIdAttribute());
        this.parameter = cb.parameter(Collection.class);
        return path.in(this.parameter);
    }
}

Criteria 查询,我也不是很熟。没办法给你讲清楚。我实际上开发,都是用

JPA + QueryDSL

这套组合。一般复杂点儿的查询,我都是用QueryDSL而不用Criteria 。

好的,我再去找找资料。再次感谢

1 个赞