基于JPA封装的BaseService

原文链接: https://ace.rthinkingsoft.cn/guide/quick-start.html

JPA-快速开始

我们将通过一个简单的 Demo 来阐述 BaseService 的强大功能,在此之前,我们假设您已经:

  • 拥有 Java 开发环境以及相应 IDE
  • 熟悉 Spring Boot
  • 熟悉 Maven

配置

xxxService 类上继承BaseService:

@Service
public class TestService extends BaseService<Merchant> {

}

(单表)获取一条数据

  • getSingleEntityById()方法

::: tip

  • 源码方法 :
  • T getSingleEntityById(Serializable id)
  • R getSingleEntityById(Class tClass, Serializable id)
    :::
    /**
     * 根据Id获取一条数据 (返回类型为当前注入的实体类型)
     * @param id
     * @return Merchant
     */
    public Merchant getMerchantById(long id){
        return this.getSingleEntityById(id);
    }

    /**
     * 根据Id获取一条数据 (返回类型为自定义传入的实体类型)
     * @param id
     * @return Platform
     */
    public Platform getPlatformById(int id){
        return this.getSingleEntityById(Platform.class, id);
    }

::: tip
参数Id可以是继承Serializable的任意类型,因为BaseService里的方法参数是泛型
:::

  • 根据Sql语句查询一条数据

::: tip

  • 源码方法 :
  • Long getSingleValue(String sql)
  • Long getSingleValue(String sql, Object params)
  • T getSingleEntity(String sql)
  • R getSingleEntity(Class tClass, String sql)
  • Map getSingleMap(String sql)
    :::
    /**
     * 根据Sql获取一条数据 (返回类型为当前注入的实体类型)
     * @return Merchant
     */
    public Merchant getMerchantBySql(){
        /**
         * Sql构造器 (SqlWrapper)
         */
        String selSql = SqlWrapper.create(Merchant.class).build();
        /**
         * select * from merchant limit 1;
         */
        return this.getSingleEntity(selSql);
    }

    /**
     * 根据Sql获取一条数据 (返回类型为自定义传入的实体类型)
     * @return Platform
     */
    public Platform getPlatformBySql(){
        /**
         * Sql构造器 (SqlWrapper)
         */
        String selSql = SqlWrapper.create().build(Platform.class);
        /**
         * select * from platform limit 1;
         */
        return this.getSingleEntity(Platform.class, selSql);
    }

    /**
     * 根据Sql获取一条数据 (返回类型为当前注入的实体类型)
     * @return Merchant
     */
    public Merchant getMerchantBySqlWithCondition(String name, String merchantNo){
        /**
         * Sql构造器 (SqlWrapper)
         */
        String selSql = SqlWrapper.create(Merchant.class)
                .like(StrUtil.isNotEmpty(name), "merchant_name", name)
                .where(StrUtil.isNotEmpty(merchantNo), "merchant_no", merchantNo)
                .build();
        /**
         * select * from merchant
         * where merchant_name like '%name%'
         * and merchant_no = 'merchantNo'
         * limit 1;
         */
        return this.getSingleEntity(selSql);
    }


    /**
     * 根据Sql获取一条数据 (返回类型为Map类型)
     * @return Map
     */
    public Map<String, Object> getOrderRefundRecordBySqlWithCondition(String orderId, String merchantTradeOrderId){
        /**
         * Sql构造器 (SqlWrapper)
         */
        String selSql = SqlWrapper.create(OrderRefundRecord.class)
                .like(StrUtil.isNotEmpty(orderId), "order_id", orderId)
                .where(StrUtil.isNotEmpty(merchantTradeOrderId), "merchant_trade_order_id", merchantTradeOrderId)
                .build();
        /**
         * select * from t_order_refund_record
         * where order_id like '%orderId%'
         * and merchant_trade_order_id = 'merchantTradeOrderId'
         * limit 1;
         */
        return this.getSingleMap(selSql);
    }


    /**
     * 根据Sql获取单独一个字段,如:平均数、总和、总条数
     * @return Long
     */
    public Long getSingleValueBySqlWithCondition(){
        /**
         * Sql构造器 (SqlWrapper)
         */
        String selSql = SqlWrapper.create(MerchantInfo.class)
                .selectMax("version")
                .build();
        /**
         * select Max(version) from t_merchant_info
         */
        return this.getSingleValue(selSql);
    }

::: tip
SQLWrapper构造器还有很多高级用法,但只能用于单表的Sql拼接,暂时不支持多表联查
:::

(单表)获取AllList集合

  • getAllListEntity()方法

::: tip

  • 源码方法 :
  • List> getAllListMap()
  • List> getAllListMap(Class tClass)
  • List getAllListEntity()
  • List getAllListEntity(Class tClass)
    :::
    /**
     * 获取表中所有数据 (返回类型为当前注入的实体类型)
     * @return List
     */
    public List<Merchant> getAllMerchantList(){
        return this.getAllListEntity();
    }

    /**
     * 获取表中所有数据 (返回类型为自定义传入的实体类型)
     * @return List
     */
    public List<BankChannel> getAllBankChannelList(){
        return this.getAllListEntity(BankChannel.class);
    }

    /**
     * 获取表中所有数据 (返回类型为当前注入的实体类型)
     * @return List>
     */
    public List<Map<String, Object>> getAllMerchantListMap(){
        return this.getAllListMap();
    }

    /**
     * 获取表中所有数据 (返回类型为自定义传入的实体类型)
     * @return List>
     */
    public List<Map<String, Object>> getAllBankChannelListMap(){
        return this.getAllListMap(BankChannel.class);
    }
  

::: tip
几乎所有的方法都有两套,默认第一个参数是Class类型,
如果不传,那么就取当前继承BaseService时传入的实体类型,如果传递就取自定义的实体类型
:::

(单表)根据Sql获取List集合

  • getListEntity()方法

::: tip

  • 源码方法 :

  • List getListEntity(String sql)

  • List getListEntity(String sql, Object params)

  • List getListEntity(String sql, Pageable pageable)

  • List getListEntity(String sql, Object params, Pageable pageable)

  • Page getPagedListEntity(String sql, Pageable pageable)

  • Page getPagedListEntity(String sql, Object params, Pageable pageable)

  • List getListEntity(Class tClass, String sql)

  • List getListEntity(Class tClass, String sql, Object params)

  • List getListEntity(Class tClass, String sql, Pageable pageable)

  • List getListEntity(Class tClass, String sql, Object params, Pageable pageable)

  • Page getPagedListEntity(Class tClass, String sql, Pageable pageable)

  • Page getPagedListEntity(Class tClass, String sql, Object params, Pageable pageable)
    :::

   /**
    * Sql构造器 (SqlWrapper)
    */
   String selSql = SqlWrapper.create(BuryingPoint.class)
           //.select("id, content")
           .where("id >", 1)
           .where("name !=", "777")
           .orWhere("description !=", "777")
           .like(StrUtil.isNotEmpty("实体店"), "name", "实体店")
           .orLike(StrUtil.isNotEmpty("实体店"), "type", "实体店")
           .orGroupStart()
               .like("name", "yyyyyy")
           .groupEnd()
           .groupStart()
               .where("name !=", "777")
               .orWhere("description !=", "777")
           .groupEnd()
           .orderBy("id", "desc")
           .orderBy("name", "asc")
           .groupBy("name")
           .build();
           /*
           SELECT
               *
           FROM
               `burying_point`
           WHERE
               `id` > 1
               AND `name` != '777'
               OR `description` != '777'
               AND `name` LIKE '%实体店%' ESCAPE '!'
               OR `type` LIKE '%实体店%' ESCAPE '!'
               OR ( `name` LIKE '%yyyyyy%' ESCAPE '!' )
               AND ( `name` != '777' OR `description` != '777' )
           GROUP BY
               `name`
           ORDER BY
               `id` DESC,
               `name` ASC
           */
    /**
     * 根据Sql查询List返回 (返回类型为自定义传入的"BuryingPoint"实体类型)
      */
    List<BuryingPoint> merchantListEntity = this.getListEntity(BuryingPoint.class, selSql);

    /**
     *  取分页List数据 (返回List)
     */
    Pageable pageable = PageRequest.of(0, 10);
    List<BuryingPoint> pagedListEntity = this.getListEntity(BuryingPoint.class, selSql, pageable);


    /**
     *  取分页List数据 (返回List>)
     */
    List<Map<String, Object>> pagedListMap = this.getListMap(selSql, pageable);

::: tip
几乎所有的方法都有两套,默认第一个参数是Class类型,
如果不传,那么就取当前继承BaseService时传入的实体类型,如果传递就取自定义的实体类型
:::

  • getPagedListEntity()方法 / 获取分页数据并返回分页对象

::: tip

  • 源码方法 :
  • Page getPagedListEntity(String sql, Pageable pageable)
  • Page getPagedListEntity(String sql, Object params, Pageable pageable)
  • Page getPagedListEntity(Class tClass, String sql, Pageable pageable)
  • Page getPagedListEntity(Class tClass, String sql, Object params, Pageable pageable)
    :::
   Pageable pageable = PageRequest.of(0, 10);
   /**
   *  取分页List数据 (返回Page>)
   */
  Page<Map<String, Object>> pagedModelListMap = this.getPagedListMap(selSql, pageable);


  /**
   *  取分页List数据 (返回Page)
   */
  Page<Merchant> pagedCurrentEntityList = this.getPagedListEntity(selSql, pageable);


  /**
   *  取分页List数据 (返回Page)
   */
  Page<BuryingPoint> pagedBuryingPointEntityList = this.getPagedListEntity(BuryingPoint.class, selSql, pageable);     

::: tip
分页方法只需要传递一个正常的Sql就可以,无需关心查总条数(Count)Sql,因为方法里封装了取数据总条数的Sql,详情请看getCount(sql)方法
:::

保存数据方法

  • save()、saveBatch()、saveAndFlush()方法

::: tip

  • 源码方法 :
  • Boolean save(T entity)
  • Boolean saveAndFlush(T entity)
  • Boolean saveBatch(Collection listEntities)
  • Boolean save(Class tClass, R entity, boolean... isAutoFlush)
  • Boolean saveAndFlush(Class tClass, R entity)
  • Boolean saveBatch(Class tClass, Collection listEntities)
    :::
     /**
      * 创建当前Service泛型注入的对象并赋值
      */
     Merchant merchant = new Merchant();
     merchant.setIdPlat(6L);
     merchant.setMerchantName("特朗普的小店");
     merchant.setMerchantNo("VIP000666");
     merchant.setVipCardNuber("CARD000666");

     /**
      * 保存一条数据并返回数据Id
      */
     boolean saveRetId = this.save(merchant);


     /**
      * 创建自定义的对象并赋值
      */
     BuryingPoint buryingPoint = new BuryingPoint();
     buryingPoint.setName("消费V1");
     buryingPoint.setDescription("xx描述");
     buryingPoint.setContent("xx内容");
     buryingPoint.setType("V1");
     buryingPoint.setBuryingKey("BP_Key");

     /**
      * 保存自定义的对象一条数据并返回数据Id
      */
     boolean saveOtherRetId = this.save(BuryingPoint.class, buryingPoint);

     /**
      * 创建当前Service泛型注入的对象集合并模拟赋值
      */
     List<Merchant> merchantList = new ArrayList<>();
     for (int i = 0; i < 20 ; i++) {
         Merchant interMerchant = new Merchant();
         interMerchant.setIdPlat(6L);
         interMerchant.setMerchantName("特朗普的小店" + Convert.toStr(i));
         interMerchant.setMerchantNo("VIP000666" + Convert.toStr(i));
         interMerchant.setVipCardNuber("CARD000666" + Convert.toStr(i));
         merchantList.add(interMerchant);
     }

     /**
      * 保存多条数据并返回Bool
      */
     boolean saveStatus = this.saveBatch(merchantList);          
     
     /**
      * 保存多条数据并返回Bool (保存自定义类型,具体就不多赘述了)
      */
     boolean saveOtherStatus = this.saveBatch(Merchant.class, merchantList); 

::: tip
如果需要flush,请使用带flush后缀的方法
:::

更新数据方法

  • updateById()、updateBatch()、updateByIdAndFlush()方法

::: tip

  • 源码方法 :
  • Boolean updateById(Serializable id, T entity)
  • Boolean updateById(Class tClass, Serializable id, R entity, boolean... isAutoFlush)
  • Boolean updateByIdAndFlush(Serializable id, T entity)
  • Boolean updateByIdAndFlush(Class tClass, Serializable id, R entity)
  • Boolean updateBatch(Collection listEntities)
    :::
    /**
     * 根据Id更新实体 (当前Service泛型注入的对象)
     */
    boolean merchantUpdateStatus = this.updateById(merchant.getId(), merchant);


    /**
     * 根据Id更新实体 (自定义类型对象更新)
     */
    boolean buryingPointUpdateStatus = this.updateById(BuryingPoint.class, buryingPoint.getId(), buryingPoint);


    /**
     * 更新多条数据 (当前Service泛型注入的对象)
     */
    boolean merUpdateBatchStatus = this.updateBatch(merchantList);


    /**
     * 更新多条数据 (自定义类型对象集合) / 同save方法一致,不多赘述
     */
    boolean burUpdateBatchStatus = this.updateBatch(BuryingPoint.class, buryingPointList);            

::: tip
update方法和save方法一致
:::

保存或更新数据

  • saveOrUpdate()方法
    ::: tip
  • 源码方法 :
  • Boolean saveOrUpdate(T entity)
  • Boolean saveOrUpdateAndFlush(T entity)
  • Boolean saveOrUpdate(Class tClass, R entity, boolean... isAutoFlush)
  • Boolean saveOrUpdateAndFlush(Class tClass, R entity)
    :::
    /**
     * 保存或者更新一条记录 (当前Service泛型注入的泛型类型)
     */
    Boolean saveOrUpdateId = this.saveOrUpdate(merchant);

    /**
     * 保存或者更新一条记录 (自定义类型对象更新)
     */
    Boolean burSaveOrUpdateId = this.saveOrUpdate(BuryingPoint.class, buryingPoint);               

::: tip
保存或更新方法,底层会根据传入的实体主键Id判断是保存还是更新
:::

(公用)获取数据总条数方法

::: tip
不用手动拼接Select Count(0)语法,getCount方法中会自动拼接为: (SELECT COUNT(0) COUNT_NUM FROM (" + sql + ") AS TOTAL)
所以参数只需要传递正常查数据的Sql就可以, 使用方法如下:
:::

  • (单表) getCount()方法
    /**
     * Sql构造器
     */
    String bankCountSql = SqlWrapper.create(BankChannel.class).build();
    /**
     * 根据Sql查询数据条数
     */
    long bankCount = this.getCount(bankCountSql);
  • (多表) getCount()方法
    /**
    * 手动构建Sql语句 + 参数
    */
   String recordSql = "SELECT\n" +
           "\t* \n" +
           "FROM\n" +
           "\tt_trade_payment_record,\n" +
           "\tmerchant \n" +
           "WHERE\n" +
           "\t1 = 1 \n" +
           "\tAND t_trade_payment_record.id = merchant.id\n" +
           "\tAND t_trade_payment_record.bank_channel_name LIKE :channelName \n" +
           "\tAND t_trade_payment_record.bank_order_no LIKE :orderNo ";

   Map<String, Object> recordParams = new HashMap<>();
   recordParams.put("channelName", "%中xxxx微信%");
   recordParams.put("orderNo", "YLH%");

   /**
    * 根据Sql + 参数查询数据条数
    */
   long recordCount = this.getCount(recordSql, recordParams);   

(公用)根据Sql查询一列数据

::: tip

  • 注意事项
    1. 第一个参数是你要查询的这一列对应java里的数据类型,比如Id,数据库是bigint那么可以传递Long.class, 返回List
    1. 不区分多表和单表,只要保证查出来的是一列就可以
      :::
     /**
     * Sql构造器 构建查询一列Sql
     */
    String idListSql = SqlWrapper.create(Merchant.class).select("Id").build();

    /**
     * 根据sql查询一列数据 返回List<>
     */
    List<Long> singleColumnList = this.getSingleColumnList(Long.class, idListSql);  
    
    /**
     * 手动构建多表联合查询Sql
     */
    String singleColSql = "select m.int_1 from merchant m LEFT JOIN company c on m.id = c.company_id";

    /**
     * 根据sql查询一列数据 返回List<>
     */
    List<Boolean> singleColSqlList = this.getSingleColumnList(Boolean.class, singleColSql); 

(多表联合)获取List或者Page<>的方法

::: tip
所有的getList或者getPagedList开头的方法都支持手动拼接sql传入,用法和单表的一致,以下只做简单的示范:
:::

  • (多表) getListEntity()和getPagedListEntity()方法
   /**
    * 手动构建Sql语句 + 参数
    */
   String unionSql = "SELECT\n" +
           "\t* \n" +
           "FROM\n" +
           "\tt_trade_payment_record,\n" +
           "\tmerchant \n" +
           "WHERE\n" +
           "\t1 = 1 \n" +
           "\tAND t_trade_payment_record.id = merchant.id\n" +
           "\tAND t_trade_payment_record.bank_channel_name LIKE :channelName \n" +
           "\tAND t_trade_payment_record.bank_order_no LIKE :orderNo ";

   Map<String, Object> unionSqlParams = new HashMap<>();
   unionSqlParams.put("channelName", "%中投科信微信%");
   unionSqlParams.put("orderNo", "YLH%");

   /**
    * 根据自定义多表关联Sql + 参数查询返回Map
    */
   List<Map<String, Object>> unionListMap = this.getListMap(unionSql, unionSqlParams);

   /**
    * 根据自定义多表关联Sql + 参数查询返回List
    */
   List<CoustomXXXModel> unionListEntity = this.getListEntity(CoustomXXXModel.class, unionSql, unionSqlParams);

   /**
    * 根据自定义多表关联Sql + 参数查询返回Page>
    */
   Page<Map<String, Object>> pagedListMap1 = this.getPagedListMap(unionSql, unionSqlParams, pageable);

   /**
    * 根据自定义多表关联Sql + 参数查询返回Page
    */
   Page<CoustomXXXModel> pageListEntityCus = this.getPagedListEntity(CoustomXXXModel.class, unionSql, unionSqlParams, pageable);

#BaseService源代码

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class BaseService<T> extends BeetlSqlCoreService<T>{

    @PersistenceContext
    protected EntityManager em;


    protected final static Long DEFAULT_ID_ERROR_VALUE = -1L;

    protected final static String FIELD_UNDERSCORE_NAME = "_";

    /**
     * 默认Id字段名,如果根据实体查不到id字段,默认返回这个
     */
    protected final static String DEFAULT_ID_NAME = "id";


    /**
     * 获取SqlWrapper对象
     * @return SqlWrapper
     */
    public SqlWrapper japQuery(){
        return this.japQuery(this.getCurrentTClass());
    }

    public <R> SqlWrapper japQuery(Class<R> targetClass) {
        return SqlWrapper.create(targetClass);
    }

    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓(Select查询部分)基于EntityManager的CreateNativeQuery↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * 根据sql查询一个值 (取一个值,如:平均数,最大值,最小值, 总数)
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return long
     */
    public Long jpaGetSingleValue(String sqlOrSqlId){
       return this.jpaGetSingleValue(sqlOrSqlId, null);
    }

    /**
     * 根据sql+参数查询一个值 (取一个值,如:平均数,最大值,最小值, 总数)
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @return Long
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Long jpaGetSingleValue(String sqlOrSqlId, Map<String, Object> params){
        try {
            /**
             * 验证sql是否符合规范
             */
            String[] conditions = new String[]{","};
            if(!this.validatorSqlSpec(sqlOrSqlId, conditions)){
                throw new Exception("Sql: '"+ sqlOrSqlId +"' 传入的Sql语句包含多列,请检查Sql重新调用此方法");
            }
            Query query = this.buildQuery(sqlOrSqlId, params, null, false);
            Object singleResult = query.getSingleResult();
            return Convert.toLong(singleResult, DEFAULT_ID_ERROR_VALUE);
        } catch (Exception e) {
            log.error("BaseService.jpaGetSingleValue 异常:" + e.getMessage(), e);
        }finally{
            em.close();
        }
        return DEFAULT_ID_ERROR_VALUE;
    }



    /**
     * 根据sql查询一条记录
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return Map
     */
    public T jpaGetSingleEntity(String sqlOrSqlId){
       Map<String, Object> objectMap = this.jpaGetSingleMap(sqlOrSqlId);
       T entity = BeanUtil.mapToBean(objectMap, this.getCurrentTClass(), true);
       this.mergeLostFields(entity, objectMap);
       return entity;
    }

    /**
     * 根据sql查询一条记录
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return Map
     */
    public <R> R jpaGetSingleEntity(Class<R> tClass, String sqlOrSqlId){
        Map<String, Object> objectMap = this.jpaGetSingleMap(sqlOrSqlId);
        R entity = BeanUtil.mapToBean(objectMap, tClass, true);
        this.mergeLostFields(entity, objectMap);
        return entity;
    }


    /**
     * 根据sql查询一条记录
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return Map
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Map<String, Object> jpaGetSingleMap(String sqlOrSqlId){
        Query query = this.buildQuery(sqlOrSqlId);
        /**
         * 起始对象位置
         */
        query.setFirstResult(0);
        /**
         * 查询对象个数
         */
        query.setMaxResults(1);

        Map<String, Object> resultMap = MapUtil.createMap(HashMap.class);
        try {
            List<Map<String, Object>> resultList = query.getResultList();
            return Linq.asEnumerable(resultList).firstOrDefault();
        } catch (Exception e) {
            log.error("BaseService.jpaGetSingleMap 异常:" + e.getMessage(), e);
        }finally{
            em.close();
        }
        return resultMap;
    }

    /**
     * 根据Sql和分页参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param pageable (分页对象)
     * @return List>
     */
    public List<Map<String, Object>> jpaGetListMap(String sqlOrSqlId, Pageable pageable){
        return this.jpaGetListMap(sqlOrSqlId, null, pageable);
    }

    /**
     * 根据Sql查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return List>
     */
    public List<Map<String, Object>> jpaGetListMap(String sqlOrSqlId){
        return this.jpaGetListMap(sqlOrSqlId, null, null);
    }

    /**
     * 根据Sql和参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @return List>
     */
    public List<Map<String, Object>> jpaGetListMap(String sqlOrSqlId, Map<String, Object> params){
        return this.jpaGetListMap(sqlOrSqlId, params, null);
    }

    /**
     * 根据Sql和分页参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return List>
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public List<Map<String, Object>> jpaGetListMap(String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        Query query = this.buildQuery(sqlOrSqlId, params, pageable);
        List<Map<String, Object>> resultList=new ArrayList<>();
        try {
            resultList=query.getResultList();
        } catch (Exception e) {
            log.error("BaseService.jpaGetListMap 异常:" + e.getMessage(), e);
            return resultList;
        }finally{
            em.close();
        }
        return resultList;
    }

    /**
     * 根据SQL语句查询返回分页对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param pageable
     * @return Page>
     */
    public Page<Map<String, Object>> jpaGetPagedListMap(String sqlOrSqlId, Pageable pageable){
        return this.jpaGetPagedListMap(sqlOrSqlId, null, pageable);
    }

    /**
     * 根据SQL+参数查询返回分页对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return Page
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Page<Map<String, Object>> jpaGetPagedListMap(String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        Page<Map<String, Object>> pageModel = null;
        long totalCount = 0;

        Query query = this.buildQuery(sqlOrSqlId, params, pageable);

        List<Map<String, Object>> resultList=new ArrayList<>();
        /**
         * 获取数据总条数
         */
        totalCount = this.jpaGetCount(sqlOrSqlId, params);
        try {
            resultList=query.getResultList();
            if(Validator.isNotNull(pageable) && pageable.getPageNumber() > 0){
                pageable = PageRequest.of(pageable.getPageNumber()-1, pageable.getPageSize());
            }
            pageModel = new PageImpl<>(resultList, pageable, totalCount);
        } catch (Exception e) {
            log.error("BaseService.jpaGetPagedListMap 异常:" + e.getMessage(), e);
        }finally{
            em.close();
        }
        return pageModel;
    }

    /**
     * 根据Sql和分页参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param pageable (分页对象)
     * @return List>
     */
    public List<T> jpaGetListEntity(String sqlOrSqlId, Pageable pageable){
        return this.jpaGetListEntity(sqlOrSqlId, null, pageable);
    }

    /**
     * 根据Sql查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return List>
     */
    public List<T> jpaGetListEntity(String sqlOrSqlId){
        return this.jpaGetListEntity(sqlOrSqlId, null, null);
    }

    /**
     * 根据Sql和参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @return List>
     */
    public List<T> jpaGetListEntity(String sqlOrSqlId, Map<String, Object> params){
        return this.jpaGetListEntity(sqlOrSqlId, params, null);
    }

    /**
     * 根据Sql和分页参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return List
     */
    @SuppressWarnings("unchecked")
    public List<T> jpaGetListEntity(String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        Query query = this.buildQuery(sqlOrSqlId, params, pageable);
        List<T> resultList=new ArrayList<>();
        try {
            List<Map<String, Object>> resultListMap = query.getResultList();
            resultList = Convert.toList(this.getCurrentTClass(), resultListMap);
            this.mergeLostFields(resultList, resultListMap);
        } catch (Exception e) {
            log.error("BaseService.jpaGetListEntity 异常:" + e.getMessage(), e);
        }finally{
            em.close();
        }
        return resultList;
    }

    /**
     * 根据SQL语句查询返回分页对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param pageable
     * @return Page
     */
    public Page<T> jpaGetPagedListEntity(String sqlOrSqlId, Pageable pageable){
        return this.jpaGetPagedListEntity(sqlOrSqlId, null, pageable);
    }


    /**
     * 根据SQL+参数查询返回分页对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return Page
     */
    public Page<T> jpaGetPagedListEntity(String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        return this.jpaGetPagedListEntity(this.getCurrentTClass(), sqlOrSqlId, params, pageable);
    }


    /**
     * 根据Sql和分页参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param pageable (分页对象)
     * @return List
     */
    public <R> List<R> jpaGetListEntity(Class<R> tClass, String sqlOrSqlId, Pageable pageable){
        return this.jpaGetListEntity(tClass, sqlOrSqlId, null, pageable);
    }


    /**
     * 根据Sql查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return List
     */
    public <R> List<R> jpaGetListEntity(Class<R> tClass, String sqlOrSqlId){
        return this.jpaGetListEntity(tClass, sqlOrSqlId, null, null);
    }

    /**
     * 根据Sql和参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @return List
     */
    public <R> List<R> jpaGetListEntity(Class<R> tClass, String sqlOrSqlId, Map<String, Object> params){
        return this.jpaGetListEntity(tClass, sqlOrSqlId, params, null);
    }

    /**
     * 根据Sql和分页参数查询列表
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return List
     */
    public <R> List<R> jpaGetListEntity(Class<R> tClass, String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        List<Map<String, Object>> listMap = this.jpaGetListMap(sqlOrSqlId, params, pageable);
        List<R> resList = Convert.toList(tClass, listMap);
        this.mergeLostFields(resList, listMap);
        return resList;
    }


    /**
     * 根据SQL语句查询返回分页对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param pageable
     * @return Page
     */
    public <R> Page<R> jpaGetPagedListEntity(Class<R> tClass, String sqlOrSqlId, Pageable pageable){
        return this.jpaGetPagedListEntity(tClass, sqlOrSqlId, null, pageable);
    }

    /**
     * 根据SQL+参数查询返回分页对象
     * @author: wei.fu
     * @param tClass
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return Page
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public <R> Page<R> jpaGetPagedListEntity(Class<R> tClass, String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        Page<R> pageModel = null;
        Page<Map<String, Object>> pagedListMap = this.jpaGetPagedListMap(sqlOrSqlId, params, pageable);
        List<R> resultList = Convert.toList(tClass, pagedListMap.getContent());
        this.mergeLostFields(resultList, pagedListMap.getContent());
        if(Validator.isNotNull(pageable) && pageable.getPageNumber() > 0){
            pageable = PageRequest.of(pageable.getPageNumber()-1, pageable.getPageSize());
        }
        pageModel = new PageImpl<>(resultList, pageable, pagedListMap.getTotalElements());
        return pageModel;
    }

    /**
     * (基于当前注入泛型)根据Id获取一条数据
     * @author: wei.fu
     * @param id
     * @return T
     */
    public T jpaGetSingleEntityById(Serializable id){
        Serializable serId = this.convertIdType(this.getCurrentTClass(), id);
        return em.find(this.getCurrentTClass(), serId);
    }


    /**
     * (动态传入泛型)根据Id获取一条数据
     * @author: wei.fu
     * @param id
     * @return R
     */
    public <R> R jpaGetSingleEntityById(Class<R> tClass, Serializable id){
        try{
            Serializable serId = this.convertIdType(tClass, id);
            return em.find(tClass, serId);
        }catch (Exception e){
            log.error("BaseService.jpaGetSingleEntityById 异常:" + e.getMessage(), e);
            return null;
        }finally {
            em.close();
        }
    }


    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑(Select查询部分)基于EntityManager的CreateNativeQuery↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/


    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓(增删改)基于EntityManager的增删改↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/


    /**
     * (基于当前注入泛型)保存方法
     * @author: wei.fu
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaSave(T entity){
        return this.jpaSave(this.getCurrentTClass(), entity);
    }

    /**
     * (基于当前注入泛型)保存并Flush方法
     * @author: wei.fu
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaSaveAndFlush(T entity){
        return this.jpaSave(this.getCurrentTClass(), entity, true);
    }

    /**
     * (动态传入泛型)保存方法
     * @author: wei.fu
     * @param entity
     * @param isAutoFlush
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaSave(Class<R> tClass, R entity, boolean... isAutoFlush){
        boolean isFlush = isAutoFlush.length > 0 && isAutoFlush[0];
        try{
            em.persist(entity);
            return true;
        }catch (Exception e){
            log.error("BaseService.jpaSave 异常:" + e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }finally {
            if(isFlush){
                em.flush();
            }
            em.close();
        }
    }

    /**
     * (动态传入泛型)保存并刷新方法
     * @author: wei.fu
     * @param tClass
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaSaveAndFlush(Class<R> tClass, R entity){
        return this.jpaSave(tClass, entity, true);
    }

    /**
     * (基于当前注入泛型)批量更新操作
     * @author: wei.fu
     * @param listEntities
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaSaveBatch(Collection<T> listEntities){
        return this.jpaSaveBatch(this.getCurrentTClass(), listEntities);
    }

    /**
     * (动态传入泛型)批量创建操作
     * @author: wei.fu
     * @param listEntities
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaSaveBatch(Class<R> tClass, Collection<R> listEntities){
        try{
            List<R> listEntity = Convert.toList(tClass, listEntities);
            for (int i = 0; i < listEntity.size(); i++) {
                em.persist(listEntity.get(i));
                if (i % 1000 == 0) {
                    em.flush();
                }
            }
            em.flush();
            return true;
        }catch (Exception e){
            log.error("BaseService.jpaSaveBatch 异常:" + e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }finally {
            em.close();
        }
    }

    /**
     * (基于当前注入泛型)根据Id更新方法
     * @author: wei.fu
     * @param id
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaUpdateById(Serializable id, T entity){
        return this.jpaUpdateById(this.getCurrentTClass(), id, entity);
    }


    /**
     * (动态传入泛型)根据Id更新方法
     * @author: wei.fu
     * @param tClass
     * @param id
     * @param entity
     * @param 
     * @param isAutoFlush
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaUpdateById(Class<R> tClass, Serializable id, R entity, boolean... isAutoFlush){
        boolean isFlush = isAutoFlush.length > 0 && isAutoFlush[0];
        try{
            R dbEntity = this.jpaGetSingleEntityById(tClass, id);
            /**
             * 属性拷贝,忽略传入的null值转换
             */
            CopyOptions copyOptions = new CopyOptions();
            copyOptions.setIgnoreNullValue(true);
            copyOptions.setIgnoreError(true);
            copyOptions.setIgnoreCase(false);
            BeanUtil.copyProperties(entity, dbEntity, copyOptions);
            /**
             * Id重新赋传入的值
             */
            ReflectUtil.setFieldValue(dbEntity, this.getIdFieldName(tClass), id);
            em.merge(dbEntity);
            BeanUtil.copyProperties(dbEntity, entity, true);
            return true;
        }catch (Exception e){
            log.error("BaseService.jpaUpdateById 异常:" + e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }finally {
            if(isFlush){
                em.flush();
            }
            em.close();
        }
    }

    /**
     * (基于当前注入泛型)根据Id更新并Flush方法
     * @author: wei.fu
     * @param id
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaUpdateByIdAndFlush(Serializable id, T entity){
        return this.jpaUpdateById(this.getCurrentTClass(), id, entity, true);
    }

    /**
     * (动态传入泛型)根据Id更新方法并Flush
     * @author: wei.fu
     * @param tClass
     * @param id
     * @param entity
     * @param 
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaUpdateByIdAndFlush(Class<R> tClass, Serializable id, R entity){
        return this.jpaUpdateById(tClass, id, entity, true);
    }


    /**
     * (基于当前注入泛型)批量更新操作
     * @author: wei.fu
     * @param listEntities
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaUpdateBatch(Collection<T> listEntities){
       try{
           List<Boolean> retList = new ArrayList<>();
           for (T r: listEntities) {
               Serializable fieldValue = (Serializable)ReflectUtil.getFieldValue(r, this.getIdFieldName(this.getCurrentTClass()));
               retList.add(this.jpaUpdateById(this.getCurrentTClass(), fieldValue, r, false));
           }
           return Linq.asEnumerable(retList).any(c -> !c);
       }catch (Exception e){
           log.error("BaseService.jpaUpdateBatch 异常:" + e.getMessage(), e);
           TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
           return false;
       }finally {
           em.flush();
           em.close();
       }
    }


    /**
     * (基于当前注入泛型)根据Id删除一条方法
     * @author: wei.fu
     * @param id
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaDeleteById(Serializable id){
        return this.jpaDeleteById(this.getCurrentTClass(), id);
    }

    /**
     *(基于当前注入泛型)根据IdList删除多条数据
     * @author: wei.fu
     * @param idList
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaDeleteByIds(Collection<? extends Serializable> idList){
        return this.jpaDeleteByIds(this.getCurrentTClass(), idList);
    }

    /**
     * (动态传入泛型)根据Id删除一条方法
     * @author: wei.fu
     * @param id
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> boolean jpaDeleteById(Class<R> tClass, Serializable id){
        try{
            R dbEntity = this.jpaGetSingleEntityById(tClass, id);
            em.remove(dbEntity);
            return true;
        }catch (Exception e){
            log.error("BaseService.jpaDeleteById 异常:" + e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }finally {
            em.flush();
            em.close();
        }
    }

    /**
     * (动态传入泛型)根据IdList删除多条数据
     * @author: wei.fu
     * @param idList
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> boolean jpaDeleteByIds(Class<R> tClass, Collection<? extends Serializable> idList){
        try{
            for (Serializable id: idList) {
                R dbEntity = this.jpaGetSingleEntityById(tClass, id);
                em.remove(dbEntity);
            }
            return true;
        }catch (Exception e){
            log.error("BaseService.jpaDeleteByIds 异常:" + e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }finally {
            em.flush();
            em.close();
        }
    }

    /**
     * (基于当前注入泛型)根据实体Id判断是创建还是修改
     * @author: wei.fu
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaSaveOrUpdate(T entity){
        return this.jpaSaveOrUpdate(this.getCurrentTClass(), entity);
    }

    /**
     * (基于当前注入泛型)根据实体Id判断是创建还是修改并Flush
     * @author: wei.fu
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean jpaSaveOrUpdateAndFlush(T entity){
        return this.jpaSaveOrUpdate(this.getCurrentTClass(), entity, true);
    }

    /**
     * (动态传入泛型)根据实体Id判断是创建还是修改 并且Flush
     * @author: wei.fu
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaSaveOrUpdateAndFlush(Class<R> tClass, R entity){
        return this.jpaSaveOrUpdate(tClass, entity, true);
    }

    /**
     * (动态传入泛型)根据实体Id判断是创建还是修改
     * @author: wei.fu
     * @param entity
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaSaveOrUpdate(Class<R> tClass, R entity, boolean... isAutoFlush){
        Boolean retStatus = false;
        String idFieldName = this.getIdFieldName(tClass);
        Object fieldValue = ReflectUtil.getFieldValue(entity, idFieldName);
        if(Validator.isEmpty(fieldValue)){
            retStatus = this.jpaSave(tClass, entity, isAutoFlush);
        }else{
            retStatus = this.jpaUpdateById(tClass, this.convertIdType(tClass, fieldValue), entity, isAutoFlush);
        }
        return retStatus;
    }

    /**
     * (动态传入泛型)批量更新操作
     * @author: wei.fu
     * @param listEntities
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public <R> Boolean jpaUpdateBatch(Class<R> tClass, Collection<R> listEntities){
        List<Boolean> retList = new ArrayList<>();
        for (R r: listEntities) {
            Serializable fieldValue = (Serializable)ReflectUtil.getFieldValue(r, this.getIdFieldName(tClass));
            retList.add(this.jpaUpdateById(tClass, fieldValue, r));
        }
        return Linq.asEnumerable(retList).any(c -> !c);
    }


    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑(增删改)基于EntityManager的增删改↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/



    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓(通用部分)基于EntityManager↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * 根据Sql获取数据Count数
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return Long
     */
    public Long jpaGetCount(String sqlOrSqlId){
        return this.jpaGetCount(sqlOrSqlId, null);
    }

    /**
     * 根据Sql和参数获取数据Count数
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @return long
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Long jpaGetCount(String sqlOrSqlId, Map<String, Object> params){
        Long totalCount = 0L;
        try{
            if(this.isTemplateSql(sqlOrSqlId)){
                sqlOrSqlId = SqlWrapper.renderTemplate(sqlOrSqlId, params);
            }
            sqlOrSqlId = "SELECT COUNT(0) COUNT_NUM FROM (" + sqlOrSqlId + ") AS TOTAL";
            Query queryCount = this.buildQuery(sqlOrSqlId, params, null, false);
            Object singleResult = queryCount.getSingleResult();
            if(Validator.isNull(singleResult)){
                return totalCount;
            }
            return Convert.toLong(singleResult,0L);
        }catch (Exception e){
            log.error("BaseService.jpaGetCount 异常:" + e.getMessage(), e);
            return totalCount;
        }finally {
            em.close();
        }
    }


    /**
     * 查询全部数据(返回值类型为 List>)
     * @author: wei.fu
     * @return List>
     */
    public List<Map<String, Object>> getAllListMap(){
        String selAllSql = SqlWrapper.create(this.getCurrentTClass()).build();
        return this.jpaGetListMap(selAllSql);
    }

    /**
     * 查询全部数据(返回值类型为 List>)
     * @author: wei.fu
     * @param tClass
     * @return List>
     */
    public <R> List<Map<String, Object>> jpaGetAllListMap(Class<R> tClass){
        String selAllSql = SqlWrapper.create(tClass).build();
        return this.jpaGetListMap(selAllSql);
    }

    /**
     * 查询全部数据(返回值类型为 List)
     * @author: wei.fu
     * @return List
     */
    public List<T> jpaGetAllListEntity(){
        String selAllSql = SqlWrapper.create(this.getCurrentTClass()).build();
        return this.jpaGetListEntity(selAllSql);
    }

    /**
     * 查询全部数据(返回值类型为 List)
     * @author: wei.fu
     * @param tClass
     * @return List
     */
    public <R> List<R> jpaGetAllListEntity(Class<R> tClass){
        String selAllSql = SqlWrapper.create(tClass).build();
        return this.jpaGetListEntity(tClass, selAllSql);
    }


    /**
     * 根据Sql查询某一列集合(返回值类型为 List)
     * @author: wei.fu
     * @param typeClass (取决于数据库中列字段的类型,可选参数例如:Long.class, Integer.class, Date.class, Double.class ......)
     * @param sqlOrSqlId
     * @return List
     */
    public <R> List<R> jpaGetSingleColumnList(Class<R> typeClass, String sqlOrSqlId){
        return this.jpaGetSingleColumnList(typeClass, sqlOrSqlId, null);
    }


    /**
     * 根据Sql查询某一列集合(返回值类型为 List)
     * @author: wei.fu
     * @param typeClass (取决于数据库中列字段的类型,可选参数例如:Long.class, Integer.class, Date.class, Double.class ......)
     * @param sqlOrSqlId
     * @param params
     * @return List
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public <R> List<R> jpaGetSingleColumnList(Class<R> typeClass, String sqlOrSqlId, Map<String, Object> params){
        List<R> resList = new ArrayList<>();
        try {
            String[] conditions = new String[]{",", "*"};
            if(!this.validatorSqlSpec(sqlOrSqlId, conditions)){
                throw new Exception("Sql: '"+ sqlOrSqlId +"' 传入的Sql语句包含多列,请检查Sql重新调用此方法");
            }
            IEnumerable<Map<String, Object>> linqListMap = Linq.asEnumerable(this.jpaGetListMap(sqlOrSqlId, params));
            /**
             * 判断Map中至少有一个元素的才会执行if里
             */
            if(linqListMap.any(c -> c.size() <= 1)){
                /**
                 * where过滤Map不为空并且第一个元素的value有值得才取出
                 */
                resList = linqListMap.where(m -> Validator.isNotEmpty(Linq.asEnumerable(m.entrySet()).first().getValue())
                        && MapUtil.isNotEmpty(m)).select(a -> {
                    return Convert.convert(typeClass, Linq.asEnumerable(a.entrySet()).first().getValue());
                }).toList();
            }
            return resList;
        }catch (Exception e){
            log.error("BaseService.jpaGetSingleColumnList 异常:" + e.getMessage(), e);
            return resList;
        }finally {
            em.close();
        }
    }


    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑(通用部分)基于EntityManager↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/



    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓(工具类部分)基于EntityManager↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * 根据tClass转换对应的Id类型
     * @author: wei.fu
     * @param tClass
     * @param id
     * @param 
     * @return Serializable
     */
    private <R> Serializable convertIdType(Class<R> tClass, Object id){
        Serializable retId = DEFAULT_ID_ERROR_VALUE;
        String longType = "java.lang.Long";
        String intType = "java.lang.Integer";
        String strType = "java.lang.String";
        IEnumerable<Field> fields = Linq.asEnumerable(ReflectUtil.getFields(tClass));
        Field field = fields.firstOrDefault(c -> c.isAnnotationPresent(Id.class));
        String fieldType = field == null ? longType : field.getType().getName();

        if(longType.equalsIgnoreCase(fieldType)){
            retId = Convert.toLong(id, DEFAULT_ID_ERROR_VALUE);
        }else if(intType.equalsIgnoreCase(fieldType)){
            retId = Convert.toInt(id, -1);
        }else if(strType.equalsIgnoreCase(fieldType)){
            retId = Convert.toStr(id, "-1");
        }
        return retId;
    }

    /**
     * 合并丢失的字段,有一些字段在查询Map的时候自动转换为小驼峰,但是实体还是下划线分割这种的
     * @author: wei.fu
     * @param resultEntity
     * @param resultMap
     */
    private <R> void mergeLostFields(R resultEntity, Map<String, Object> resultMap){
        if(Validator.isNotNull(resultEntity) && Validator.isNotNull(resultMap)){
            /**
             * 获取所有字段看是否有属性包含 "_"
             */
            IEnumerable<Field> fields = Linq.asEnumerable(ReflectUtil.getFields(resultEntity.getClass()));
            if(fields.any(a -> a.getName().contains(FIELD_UNDERSCORE_NAME))){
                List<Field> supFields = fields.where(a -> a.getName().contains(FIELD_UNDERSCORE_NAME)).toList();
                supFields.forEach(f -> {
                    String fieldKey = UnderlineToCamelUtil.underlineToCamel(f.getName());
                    ReflectUtil.setFieldValue(resultEntity, f.getName(), resultMap.get(fieldKey));
                });
            }
        }
    }


    /**
     * 合并丢失的字段,有一些字段在查询Map的时候自动转换为小驼峰,但是实体还是下划线分割这种的
     * @author: wei.fu
     * @param resultList
     * @param resultListMap
     */
    private <R> void mergeLostFields(List<R> resultList, List<Map<String, Object>> resultListMap) {
        if(resultList.size() == resultListMap.size()){
            IEnumerable<R> linqList = Linq.asEnumerable(resultList);
            if(linqList.any() && Validator.isNotNull(linqList.first())){
                R firstEntity = linqList.first();
                IEnumerable<Field> fields = Linq.asEnumerable(ReflectUtil.getFields(firstEntity.getClass()));
                if(fields.any(a -> a.getName().contains(FIELD_UNDERSCORE_NAME))){
                    List<Field> supFields = fields.where(a -> a.getName().contains(FIELD_UNDERSCORE_NAME)).toList();
                    /**
                     * 遍历转换后的结果集
                     */
                    for (int i = 0; i < resultList.size(); i++) {
                        R tEntity = resultList.get(i);
                        Map<String, Object> rMap = resultListMap.get(i);
                        supFields.forEach(f -> {
                            String fieldKey = UnderlineToCamelUtil.underlineToCamel(f.getName());
                            ReflectUtil.setFieldValue(tEntity, f.getName(), rMap.get(fieldKey));
                        });
                    }
                }
            }
        }
    }


    /**
     * 判断Sql是否合法
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param condition
     * @return
     */
    private Boolean validatorSqlSpec(String sqlOrSqlId, String... condition) {
        int startPos = StrUtil.indexOfIgnoreCase(sqlOrSqlId, "select");
        int endPos = StrUtil.indexOfIgnoreCase(sqlOrSqlId, "from");
        String selectSql = StrUtil.sub(sqlOrSqlId, startPos, endPos);
        if(Validator.isNull(condition) || startPos <= 0 || endPos <= 0){
            return true;
        }
        /**
         * 判断字符串中是否包含传递过来的condition
         */
        IEnumerable<String> retList = Linq.asEnumerable(condition).where(c -> StrUtil.containsIgnoreCase(selectSql, c));
        return !retList.any();
    }




    /**
     * 获取当前泛型的Class
     * @author: wei.fu
     * @return Class
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private Class<T> getCurrentTClass(){
        Class <T> entityClass = null;
        try{
           entityClass = (Class <T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }catch (Exception e){
            log.error("BaseService.getCurrentTClass 异常:" + e.getMessage(), e);
        }
        return entityClass;
    }

    /**
     * 公用的 - 构建Query对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @return Query
     */
    public Query buildQuery(String sqlOrSqlId){
        return this.buildQuery(sqlOrSqlId, null, null, true);
    }

    /**
     * 公用的 - 构建Query对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @return Query
     */
    public Query buildQuery(String sqlOrSqlId, Map<String, Object> params){
        return this.buildQuery(sqlOrSqlId, params, null, true);
    }

    /**
     * 公用的 - 构建Query对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @return Query
     */
    public Query buildQuery(String sqlOrSqlId, Map<String, Object> params, Pageable pageable){
        return this.buildQuery(sqlOrSqlId, params, pageable, true);
    }

    /**
     * 公用的 - 构建Query对象
     * @author: wei.fu
     * @param sqlOrSqlId
     * @param params
     * @param pageable
     * @param isRetMap (是否返回Map)
     * @return Query
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Query buildQuery(String sqlOrSqlId, Map<String, Object> params, Pageable pageable, Boolean isRetMap){
        if(this.isTemplateSql(sqlOrSqlId)){
            sqlOrSqlId = SqlWrapper.renderTemplate(sqlOrSqlId, params);
        }
        Query query = em.createNativeQuery(sqlOrSqlId);

        if(params != null){
            for(String key : params.keySet()){
                if(StrUtil.containsIgnoreCase(sqlOrSqlId, StrUtil.format(":{}", key))){
                    query.setParameter(key, params.get(key));
                }
            }
        }
        if (null != pageable && pageable.getPageNumber() >= 0 && pageable.getPageSize() != 0) {
            /**
             * 起始对象位置
             */
            query.setFirstResult(pageable.getPageSize() * (pageable.getPageNumber() - 1));
            /**
             * 查询对象个数
             */
            query.setMaxResults(pageable.getPageSize());
        }
        if(isRetMap){
            /**
             * 转换小驼峰返回
             */
            query.unwrap(NativeQueryImpl.class).setResultTransformer(new HashMapResultTransformer(HashMap.class));
        }
       return query;
    }


    /**
     * 根据clazz获取主键字段Name
     * @author: wei.fu
     * @param clazz
     * @param 
     * @return String
     */
    private <R> String getIdFieldName(Class<R> clazz){
        try{
            String fieldName = Linq.asEnumerable(ReflectUtil.getFields(clazz)).where(c ->
                    c.isAnnotationPresent(AssignID.class)
                    || c.isAnnotationPresent(SeqID.class)
                    || c.isAnnotationPresent(Id.class)
                    ||c.isAnnotationPresent(AutoID.class)).select(a -> a.getName()).distinct().firstOrDefault();
            return StrUtil.isNotEmpty(fieldName) ? fieldName : DEFAULT_ID_NAME;
        }catch (Exception e){
            log.error("BeetlSqlBaseService.internalGetIdFieldName 异常:" + e.getMessage(), e);
            return DEFAULT_ID_NAME;
        }
    }


    /**
     * 根据传入的SqlId参数自动判断是sql还是SqlId
     * @param sqlOrSqlId
     * @return String
     */
    private Boolean isTemplateSql(String sqlOrSqlId){
        String absolutePath = SqlTemplate.classPathResource.getAbsolutePath();
        String removeAllLineBreakStr = StrUtil.removeAllLineBreaks(sqlOrSqlId);
        List<String> splitStrList = Linq.asEnumerable(StrUtil.split(removeAllLineBreakStr.replace("\t", ""), ".")).toList();

        if(splitStrList.size() > 0) {
            splitStrList.remove(splitStrList.size() - 1);
        }
        if(splitStrList.size() >= 1 && splitStrList.size() <= 6){
            String joinPath = CollUtil.join(splitStrList, "/");
            /**
             * 判断Sql文件是否存在
             */
            if(FileUtil.exist(StrUtil.format("{}/{}.md", absolutePath, joinPath)) || FileUtil.exist(StrUtil.format("{}/{}.sql", absolutePath, joinPath))){
                return true;
            }
        }
        return false;
    }

    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑(工具类部分)基于EntityManager↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/

}

::: tip
以上只是简单的Demo,具体实践中一定要活学活用,还有更多好玩的用法等着你来探索
:::

你可能感兴趣的:(基于JPA封装的BaseService)