All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.dengchen2020.jdbc.base.BaseJdbcRepositoryImpl Maven / Gradle / Ivy

Go to download

jdbc扩展,基于spring-boot-starter-data-jdbc实现,提供CRUD通用操作,分页,内外连接查询,支持jpa注解,乐观锁,数据填充等功能

There is a newer version: 0.0.30
Show newest version
package io.github.dengchen2020.jdbc.base;

import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.sql.RelationalPath;
import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.dml.SQLDeleteClause;
import com.querydsl.sql.dml.SQLUpdateClause;
import io.github.dengchen2020.core.querydsl.DEntityPathResolver;
import io.github.dengchen2020.core.support.model.PageParam;
import io.github.dengchen2020.core.support.model.SimplePage;
import io.github.dengchen2020.core.utils.SqlMetaUtils;
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.repository.support.SimpleJdbcRepository;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.lang.NonNull;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * BaseJdbcRepository的实现
 *
 * @author dengchen
 * @since 2024/6/16
 */
@Transactional(propagation = Propagation.SUPPORTS)
public class BaseJdbcRepositoryImpl extends SimpleJdbcRepository implements BaseJdbcRepository {

    protected final SQLQueryFactory queryFactory;

    protected final NamedParameterJdbcOperations operations;

    protected final PersistentEntity entity;

    private final String cacheKeyPrefix;

    public BaseJdbcRepositoryImpl(JdbcAggregateOperations entityOperations, PersistentEntity entity, JdbcConverter converter, NamedParameterJdbcOperations operations, SQLQueryFactory queryFactory) {
        super(entityOperations, entity, converter);
        this.queryFactory = queryFactory;
        this.operations = operations;
        this.entity = entity;
        this.cacheKeyPrefix = "cache:" + entity.getName() + "#";
    }

    protected RelationalPath entityPath(Class domainClass){
        return (RelationalPath) DEntityPathResolver.INSTANCE.createPath(domainClass);
    }

    @SuppressWarnings("unchecked")
    protected Optional findOptional(Serializable id, Function> action){
        if(TransactionSynchronizationManager.isActualTransactionActive()){
            String cacheKey = cacheKeyPrefix + id;
            Object obj = TransactionSynchronizationManager.getResource(cacheKey);
            if(obj != null) {
                return (Optional) obj;
            }
            Optional optional = action.apply(id);
            if(optional.isPresent()) {
                TransactionSynchronizationManager.bindResource(cacheKey, optional);
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                    @Override
                    public void beforeCompletion() {
                        TransactionSynchronizationManager.unbindResource(cacheKey);
                    }
                });
                return optional;
            }
        }
        return action.apply(id);
    }

    @SuppressWarnings("unchecked")
    protected T find(Serializable id, Function action){
        if(TransactionSynchronizationManager.isActualTransactionActive()){
            String cacheKey = cacheKeyPrefix + id;
            Object obj = TransactionSynchronizationManager.getResource(cacheKey);
            if(obj != null) {
                return (T) obj;
            }
            T t = action.apply(id);
            if(t != null) {
                TransactionSynchronizationManager.bindResource(cacheKey, t);
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                    @Override
                    public void beforeCompletion() {
                        TransactionSynchronizationManager.unbindResource(cacheKey);
                    }
                });
                return t;
            }
        }
        return action.apply(id);
    }

    /**
     * 新增或修改
     *
     * @param entity must not be {@literal null}.
     * @param  S
     * @return S
     */
    @NonNull
    @Override
    public  S save(@NonNull final S entity) {
        try {
            return super.save(entity);
        } catch (Exception e) {
            throw new RuntimeException("数据保存失败,值:" + entity, e);
        }
    }

    @Override
    public int softDelete(@NonNull Iterable ids) {
        if(ids.spliterator().getExactSizeIfKnown() == 0){
            return 0;
        }
        return operations.update("UPDATE " + SqlMetaUtils.init(entity.getType()).getTableName() + " SET deleted = 1 WHERE id in (:ids)", new MapSqlParameterSource("ids",ids));
    }

    @Override
    public void deleteById(@NonNull Serializable id) {
        super.deleteById(id);
    }

    @Override
    public void deleteAll() {
        throw new UnsupportedOperationException("不支持无条件的全量删除,防止误操作,请自行实现");
    }

    @Override
    public int delete(@NonNull Iterable ids) {
        if(ids.spliterator().getExactSizeIfKnown() == 0) return 0;
        SqlMetaUtils.TableInfo tableInfo = SqlMetaUtils.init(entity.getType());
        return operations.update("DELETE FROM " + tableInfo.getTableName() + " WHERE " + tableInfo.getIdColumn() + " in (:ids)", new MapSqlParameterSource("ids",ids));
    }

    @NonNull
    @Override
    public T selectByIdForUpdate(@NonNull Serializable id){
        return find(id , (s) -> {
            SqlMetaUtils.TableInfo tableInfo = SqlMetaUtils.init(entity.getType());
            String sql = "SELECT " + tableInfo.getSelectAllSql() + " FROM " + tableInfo.getTableName() + " WHERE " + tableInfo.getIdColumn() + " = :id FOR UPDATE";
            List list = operations.query(sql, new MapSqlParameterSource("id", s), new BeanPropertyRowMapper<>(entity.getType()));
            return CollectionUtils.isEmpty(list) ? null : list.getFirst();
        });
    }

    @NonNull
    @Override
    public Optional findByIdForUpdate(@NonNull Serializable id){
        return findOptional(id , (s) -> {
            SqlMetaUtils.TableInfo tableInfo = SqlMetaUtils.init(entity.getType());
            String sql = "SELECT " + tableInfo.getSelectAllSql() + " FROM " + tableInfo.getTableName() + " WHERE " + tableInfo.getIdColumn() + " = :id FOR UPDATE";
            List list = operations.query(sql, new MapSqlParameterSource("id", s), new BeanPropertyRowMapper<>(entity.getType()));
            return CollectionUtils.isEmpty(list) ? Optional.empty() : Optional.ofNullable(list.getFirst());
        });
    }

    @NonNull
    @Override
    public Optional findById(@NonNull Serializable id) {
        return findOptional(id , super::findById);
    }

    /**
     * 最基础的查询构造器
     * @return SQLQuery
     */
    @Override
    public SQLQuery query() {
        return queryFactory.query();
    }

    /**
     * 查询构造
     *
     * @param expr querydsl查询Q类对象
     * @return SQLQuery
     */
    @Override
    public  SQLQuery select(Expression expr) {
        return queryFactory.select(expr);
    }

    /**
     * 单表查询构造
     *
     * @param exprs querydsl查询Q类对象
     * @return SQLQuery
     */
    @Override
    public SQLQuery select(Expression... exprs) {
        return queryFactory.select(exprs);
    }

    /**
     * 去重查询
     * @param expr 条件
     * @return SQLQuery
     */
    @Override
    public  SQLQuery selectDistinct(Expression expr) {
        return queryFactory.select(expr).distinct();
    }

    /**
     * 去重查询
     * @param exprs 条件
     * @return SQLQuery
     */
    @Override
    public SQLQuery selectDistinct(Expression... exprs) {
        return queryFactory.select(exprs).distinct();
    }

    /**
     * select 0
     * @return SQLQuery
     */
    @Override
    public SQLQuery selectZero() {
        return select(Expressions.ZERO);
    }

    /**
     * select 1
     * @return SQLQuery
     */
    @Override
    public SQLQuery selectOne() {
        return select(Expressions.ONE);
    }

    /**
     * 单表查询构造
     *
     * @param expr querydsl查询Q类对象
     * @return SQLQuery
     */
    @Override
    public  SQLQuery selectFrom(RelationalPath expr) {
        return select(expr).from(expr);
    }

    /**
     * 按条件查询单条数据
     * @param predicate 条件
     * @return Optional
     */
    @Override
    public Optional findOne(Predicate predicate){
        return Optional.ofNullable(selectFrom(entityPath(entity.getType())).where(predicate).fetchFirst());
    }

    /**
     * 按条件查询
     * @param predicate 查询条件
     * @return Iterable
     */
    @Override
    public List findAll(Predicate predicate){
        return selectFrom(entityPath(entity.getType())).where(predicate).fetch();
    }

    /**
     * 按条件筛选查询全部
     * @param predicate 查询条件
     * @param orders 排序方式
     * @return Iterable
     */
    @Override
    public List findAll(Predicate predicate, OrderSpecifier... orders){
        return selectFrom(entityPath(entity.getType())).where(predicate).orderBy(orders).fetch();
    }

    /**
     * 按条件筛选查询全部
     * @param orders 排序方式
     * @return Iterable
     */
    @Override
    public List findAll(OrderSpecifier... orders){
        return selectFrom(entityPath(entity.getType())).orderBy(orders).fetch();
    }

    /**
     * 统一查询,支持分页
     * @param param 查询参数
     * @return SQLQuery
     */
    @Override
    public SQLQuery findAllQuery(P param){
        return selectFrom(entityPath(entity.getType()));
    }

    /**
     * Querydsl分页查询
     * @param query SQLQuery
     * @param param 分页参数
     * @param o 排序方式
     * @return SimplePage
     */
    @Override
    public  SimplePage pageList(SQLQuery query, PageParam param, OrderSpecifier... o){
        if (param.getSize() != null && param.getSize() == 0) return new SimplePage<>(query.fetchCount(), Collections.emptyList());
        if (o != null && o.length > 0) query = query.orderBy(o);
        if (!param.isSelectCount()) {
            return new SimplePage<>(null, query.limit(param.getSize())
                    .offset(param.getOffset())
                    .fetch());
        }
        QueryResults result = query.limit(param.getSize())
                .offset(param.getOffset())
                .fetchResults();
        return new SimplePage<>(result.getTotal(), result.getResults());
    }

    /**
     * Querydsl分页条件查询
     *
     * @param param 分页参数
     * @param o     排序方式
     * @return 分页后的数据
     */
    @Override
    public SimplePage findAll(Predicate predicate, PageParam param, OrderSpecifier... o){
        return pageList(selectFrom(entityPath(entity.getType())).where(predicate), param, o);
    }

    /**
     * 返回流读取器
     * @param query SQLQuery
     * @param param 查询参数
     * @param o 排序方式
     * @return Stream
     */
    @Override
    public  Stream streamList(SQLQuery query, PageParam param, OrderSpecifier... o){
        if (o != null && o.length > 0) query = query.orderBy(o);
        if(param == null) return query.stream();
        return query.limit(param.getSize())
                .offset(param.getOffset())
                .stream();
    }

    /**
     * 返回流读取器
     * @param predicate 条件
     * @param param 查询参数
     * @param o 排序方式
     * @return Stream
     */
    @Override
    public Stream findStream(Predicate predicate, PageParam param, OrderSpecifier... o){
        return streamList(selectFrom(entityPath(entity.getType())).where(predicate), param, o);
    }

    /**
     * 返回流读取器
     * @param param 查询参数
     * @param o 排序方式
     * @return Stream
     */
    @Override
    public Stream findStream(PageParam param, OrderSpecifier... o){
        return streamList(selectFrom(entityPath(entity.getType())), param, o);
    }

    /**
     * 返回流读取器
     * @param o 排序方式
     * @return Stream
     */
    @Override
    public Stream findStream(OrderSpecifier... o){
        return streamList(selectFrom(entityPath(entity.getType())), null, o);
    }

    /**
     * 统计数量
     * @param predicate 查询条件
     * @return 数量
     */
    @Override
    public long count(Predicate predicate){
        return selectFrom(entityPath(entity.getType())).where(predicate).fetchCount();
    }

    /**
     * 是否存在
     * @param predicate 查询条件
     * @return true or false
     */
    @Override
    public boolean exists(Predicate predicate){
        return selectOne().from(entityPath(entity.getType())).where(predicate).fetchFirst() != null;
    }

    /**
     * 更新构造
     *
     * @param path  要更新数据的表名
     * @param where 更新条件
     * @return SQLUpdateClause
     */
    @Override
    public SQLUpdateClause update(RelationalPath path, Predicate[] where) {
        if (where == null || where.length == 0) throw new RuntimeException("更新必须有条件");
        return queryFactory.update(path).where(where);
    }

    /**
     * 更新构造
     *
     * @param path  要更新数据的表名
     * @param where 更新条件
     * @return SQLUpdateClause
     */
    @Override
    public SQLUpdateClause update(RelationalPath path, Predicate where) {
        return update(path, new Predicate[]{where});
    }

    /**
     * 删除构造
     *
     * @param path  要删除数据的表名
     * @param where 删除条件
     * @return SQLDeleteClause
     */
    @Override
    public SQLDeleteClause delete(RelationalPath path, Predicate[] where) {
        if (where == null || where.length == 0) throw new RuntimeException("删除必须有条件");
        return queryFactory.delete(path).where(where);
    }

    /**
     * 删除构造
     *
     * @param path  要删除数据的表名
     * @param where 删除条件
     * @return SQLDeleteClause
     */
    @Override
    public SQLDeleteClause delete(RelationalPath path, Predicate where) {
        return delete(path, new Predicate[]{where});
    }

}