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

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

There is a newer version: 1.4.0
Show newest version
package com.kasinf.framework.rest.repository;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import com.kasinf.framework.rest.eneity.AbstractEntity;
import com.kasinf.framework.rest.repository.callback.SearchCallback;
import com.kasinf.framework.rest.eneity.type.LogicDeletable;
import com.kasinf.framework.rest.support.Searchable;
import lombok.Setter;
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 static final String LOGIC_DELETE_ALL_QUERY_STRING = "update %s x set x.isDelete=true where x in ?1";
    private static final String DELETE_ALL_QUERY_STRING = "delete from %s x where x in ?1";
    private static final String FIND_QUERY_STRING = "select x from %s x where 1=1 ";
    private static final String COUNT_QUERY_STRING = "select count(x) from %s x where 1=1 ";

    protected final EntityManager em;

    protected final Class entityClass;
    protected final JpaEntityInformation entityInformation;
    protected final String entityName;
    protected final String idName;

    private String findAllQL;
    private String countAllQL;

    private SearchCallback searchCallback = SearchCallback.DEFAULT;

    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();

        findAllQL = String.format(FIND_QUERY_STRING, entityName);
        countAllQL = String.format(COUNT_QUERY_STRING, entityName);
    }

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

    /**
     * 删除对应实体,需要考虑是否是逻辑删除
     *
     * @param t 要删除的实体
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void delete(T t) {
        Assert.notNull(t, "Entity must not be null!");
        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);

            String ql = LogicDeletable.class.isAssignableFrom(this.entityClass) ?
                    String.format(LOGIC_DELETE_ALL_QUERY_STRING, entityName) :
                    String.format(DELETE_ALL_QUERY_STRING, entityName);

            Query query = em.createQuery(ql);
            setParameters(query, models);
            query.executeUpdate();
        }
    }

    /**
     * 删除全部,考虑逻辑删除,若要清空逻辑对象表的数据,需要在接口覆盖此方法
     */
    @Override
    @Transactional(rollbackOn = Exception.class)
    public void deleteAll() {
        String ql = LogicDeletable.class.isAssignableFrom(this.entityClass) ?
                String.format(LOGIC_DELETE_ALL_QUERY_STRING.replace("where x in ?1", ""), entityName) :
                String.format(DELETE_ALL_QUERY_STRING.replace("where x in ?1", ""), entityName);
        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());
        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());
        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]);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy