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

com.kasinf.framework.rest.repository.BaseRepositoryImpl Maven / Gradle / Ivy

The newest version!
package com.kasinf.framework.rest.repository;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.kasinf.framework.rest.annotation.EnableQueryCache;
import com.kasinf.framework.rest.annotation.LogicDelete;
import com.kasinf.framework.rest.eneity.AbstractEntity;
import com.kasinf.framework.rest.eneity.type.LogicDeletable;
import com.kasinf.framework.rest.repository.callback.SearchCallback;
import com.kasinf.framework.rest.support.Searchable;
import lombok.Setter;
import org.hibernate.jpa.QueryHints;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.util.Assert;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
import java.io.Serializable;
import java.util.*;

/**
 * 基础存储库实现
 *
 * @author lkhsh
 */
@Setter
public class BaseRepositoryImpl extends SimpleJpaRepository implements BaseRepository {

    private final String LOGIC_DELETE_ALL_QUERY_STRING;
    private final String DELETE_ALL_QUERY_STRING;

    /**
     * 实体管理器
     */
    protected final EntityManager em;
    /**
     * 当前实体类
     */
    protected final Class entityClass;

    protected final JpaEntityInformation entityInformation;

    /**
     * 实体类全限定名
     */
    protected final String entityName;

    /**
     * 主键名
     */
    protected final String idName;

    /**
     * 逻辑删除的字段
     */
    protected final LogicDelete logicDelete;

    /**
     * 查询缓存设置
     */
    protected final boolean enableQueryCache;

    /**
     * 缓存区域
     */
    protected final String cacheRegion;

    /**
     * 逻辑删除的值,转换之后的
     */
    protected final Object deleteValue;

    /**
     * 查询回调
     */
    private SearchCallback searchCallback = SearchCallback.DEFAULT;

    private String countAllQl;
    private String findAllQl;

    public BaseRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);

        this.em = entityManager;
        this.entityInformation = entityInformation;
        this.entityClass = entityInformation.getJavaType();
        this.entityName = entityInformation.getEntityName();
        this.idName = entityInformation.getIdAttributeNames().iterator().next();

        logicDelete = getLogicDelete(entityClass);
        DELETE_ALL_QUERY_STRING = String.format("delete from %s x where x in :ids", entityName);
        countAllQl = String.format("select count(x) from %s x where 1=1 ", entityName);
        findAllQl = String.format("select x from %s x where 1=1 ", entityName);
        if (logicDelete != null) {
            deleteValue = Convert.convert(logicDelete.type(), logicDelete.value());
            LOGIC_DELETE_ALL_QUERY_STRING = String.format("update %s x set x.%s=:deleteValue where x in :ids", entityName, logicDelete.of());
        } else {
            deleteValue = null;
            LOGIC_DELETE_ALL_QUERY_STRING = "";
        }

        EnableQueryCache queryCache = getEnableQueryCache(entityClass);
        if (queryCache != null) {
            enableQueryCache = queryCache.value();
            cacheRegion = queryCache.region();
        } else {
            enableQueryCache = false;
            cacheRegion = null;
        }
    }

    /**
     * 获取自身或者父类上的 @EnableQueryCache 注解。
     *
     * @param entityClass 目标类
     * @return {@link EnableQueryCache}
     */
    private EnableQueryCache getEnableQueryCache(Class entityClass) {
        EnableQueryCache enableQueryCacheAnnotation = AnnotationUtils.findAnnotation(entityClass, EnableQueryCache.class);
        if (enableQueryCacheAnnotation == null && entityClass.getSuperclass() != null && !"java.lang.Object".equals(entityClass.getSuperclass().getName())) {
            return getEnableQueryCache(entityClass.getSuperclass());
        }
        return enableQueryCacheAnnotation;
    }

    /**
     * 获取自身或者其父类上的 @LogicDelete 注解。
     *
     * @param entityClass 目标类
     * @return {@link LogicDelete}
     */
    private LogicDelete getLogicDelete(Class entityClass) {
        LogicDelete logicDelete = AnnotationUtil.getAnnotation(entityClass, LogicDelete.class);
        if (logicDelete == null && entityClass.getSuperclass() != null && !"java.lang.Object".equals(entityClass.getSuperclass().getName())) {
            return getLogicDelete(entityClass.getSuperclass());
        }
        return logicDelete;
    }

    /////////////////////////////////////////////////
    ////////覆盖默认spring data jpa的实现////////////
    /////////////////////////////////////////////////

    /**
     * 删除对应实体,需要考虑是否是逻辑删除
     *
     * @param t 要删除的实体
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void delete(T t) {
        Assert.notNull(t, "Entity must not be null!");
        if (logicDelete != null) {
            // 注入属性
            ReflectUtil.invoke(t, StrUtil.upperFirstAndAddPre(logicDelete.of(), "set"), deleteValue);
            save(t);
        } else if (t instanceof LogicDeletable) {
            ((LogicDeletable) t).markDeleted();
            save(t);
        } else {
            super.delete(t);
        }
    }

    /**
     * 通过ID删除对象,添加逻辑删除的考虑
     *
     * @param id 对象ID
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void deleteById(ID id) {
        T t = super.getOne(id);
        delete(t);
    }

    /**
     * 删除指定对象列表,考虑对逻辑删除实体的操作
     *
     * @param entities 对象列表
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void deleteInBatch(Iterable entities) {
        Iterator iter = entities.iterator();
        if (iter.hasNext()) {
            Set models = new HashSet<>();
            iter.forEachRemaining(models::add);

            Query query = em.createQuery(
                    logicDelete != null ?
                            LOGIC_DELETE_ALL_QUERY_STRING :
                            (LogicDeletable.class.isAssignableFrom(this.entityClass)) ?
                                    String.format("update %s x set x.isDelete=true where x in :ids", entityName) :
                                    DELETE_ALL_QUERY_STRING);
            query.setParameter("ids", models);
            if (logicDelete != null) {
                query.setParameter("deleteValue", deleteValue);
            }
            query.executeUpdate();
        }
    }

    /**
     * 删除全部,考虑逻辑删除,若要清空逻辑对象表的数据,需要在接口覆盖此方法
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void deleteAll() {
        String ql = logicDelete != null ?
                LOGIC_DELETE_ALL_QUERY_STRING.replace("where x in ?1", "") :
                (LogicDeletable.class.isAssignableFrom(this.entityClass)) ?
                        String.format("update %s x set x.isDelete=true", entityName) :
                        DELETE_ALL_QUERY_STRING.replace("where x in ?1", "");
        Query query = em.createQuery(ql);
        query.executeUpdate();
    }

    @Override
    public boolean existsById(ID id) {
        return findById(id).isPresent();
    }

    /////////////////////////////////////////////////
    ///////////////////自定义实现////////////////////
    /////////////////////////////////////////////////

    @Override
    public T findOne(ID id) {
        Optional t = findById(id);
        return t.orElse(null);
    }

    /**
     * 通过指定的ID数组删除对象,考虑对逻辑删除的处理
     *
     * @param ids 要删除的id数组
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void deleteInBatch(ID[] ids) {
        if (ArrayUtil.isNotEmpty(ids)) {
            Set models = new HashSet<>(ids.length);
            for (ID id : ids) {
                T model;
                try {
                    model = entityClass.newInstance();
                } catch (Exception e) {
                    throw new RuntimeException("batch delete " + entityClass + " exception", e);
                }
                try {
                    ReflectUtil.setFieldValue(model, idName, id);
                } catch (Exception e) {
                    throw new RuntimeException("batch delete " + entityClass + " exception, can not set id", e);
                }
                models.add(model);
            }
            deleteInBatch(models);
        }
    }

    @Override
    public Page findAll(Searchable searchable) {
        List list = this.findAll(findAllQl, searchable, searchCallback);
        long total = searchable.hasPageable() ? count(searchable) : list.size();
        return new PageImpl(list, searchable.getPage(), total);
    }

    @Override
    public List findList(Searchable searchable) {
        return this.findAll(findAllQl, searchable, searchCallback);
    }

    @Override
    public long count(Searchable searchable) {
        return this.count(countAllQl, searchable, searchCallback);
    }

    /**
     * 按条件统计
     *
     * @param ql             基本查询语句
     * @param searchable     查询条件、分页、排序
     * @param searchCallback 查询回调,自定义设置查询条件和赋值
     */
    private long count(final String ql, final Searchable searchable, final SearchCallback searchCallback) {
        searchable.changeDataCondition();
        assertConverted(searchable);

        StringBuilder s = new StringBuilder(ql);
        searchCallback.prepareQl(s, searchable);
        Query query = em.createQuery(s.toString());
        applyEnableQueryCache(query);
        searchCallback.setValues(query, searchable);
        return (Long) query.getSingleResult();
    }

    /**
     * @param ql             基本查询语句
     * @param searchable     查询条件、分页、排序
     * @param searchCallback 查询回调,自定义设置查询条件和赋值
     */
    private List findAll(final String ql, final Searchable searchable, final SearchCallback searchCallback) {
        searchable.changeDataCondition();
        assertConverted(searchable);
        StringBuilder s = new StringBuilder(ql);
        searchCallback.prepareQl(s, searchable);
        searchCallback.prepareOrder(s, searchable);
        Query query = em.createQuery(s.toString());
        applyEnableQueryCache(query);
        searchCallback.setValues(query, searchable);
        searchCallback.setPageable(query, searchable);
        return query.getResultList();
    }

    private void assertConverted(Searchable searchable) {
        if (!searchable.isConverted()) {
            searchable.convert(this.entityClass);
        }
    }

    /**
     * 按顺序设置Query参数
     *
     * @param query:查询
     * @param params:参数
     */
    private void setParameters(Query query, Object... params) {
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i + 1, params[i]);
            }
        }
    }

    public void applyEnableQueryCache(Query query) {
        if (enableQueryCache) {
            //开启查询缓存
            query.setHint(QueryHints.HINT_CACHEABLE, true);
        }
        if (cacheRegion != null) {
            //设置缓存区域
            query.setHint(QueryHints.HINT_CACHE_REGION, cacheRegion);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy