适用于通用mapper的BaseService升级版

上次写了一篇博客适用于Generator mybatis 生成器的通用BaseService

这次是上次的升级版,因为在开发的过程中发现,mybatisGenerator生成器生成的代码有个弊端,虽然大大解放了我们双手,减少了CURD的代码的编写,但是当我们业务需求发生变动的时候,如数据库新增一条字段,这样我们必须重新在使用MG(mybatisGenerator )生成一次非常麻烦,而这次是通过引入通用mapper来解决此问题,通用mapper插件。通用mapper它只生成mapper.xml的实体类映射和一个继承自己的专属mapper,生成的mapper接口没有方法,因为所有的CURD方法都继承了父类,所以当我们如数据库新增一个字段的时候,我们只需要修改po类和mapper.xml映射字段,很方便,CURD操作也非常多,基本上解决了90%的CURD操作,还没学过使用通用mapper的可以下面链接学习。

通用mapper学习通用mapper学习

这次封装的BaseService的底层用的是通用mapper,只需要自己的service继承该service,就实现了各种CURD操作,后期在借助我将要公布的BaseController和通用mapper,po,service,controller生成器,基本上不用手写一行代码,可以完成90%的单表操作,你只需要专注前端的接口调用设计就行了,BaseService代码如下。

/**
 * 基本Service
 *
 * @auther ny by:dbw
 * @create 2018-06-09
 */

public class BaseService<T>  {

    private Class<T> cache=null;  //缓存子类泛型类型


    @Autowired
    Mapper<T> mapper;

    T clazz;

    /**
     * 添加
     * @param t
     * @return
     */
    public T add(T t){
        System.out.println(t);
        int i = mapper.insertSelective(t);
        if(i>0)
          return t;
        else
          return null;
    }

    /**
     * 删除 by 主键key
     * @param  t
     */
    public void delete(T t){
        mapper.deleteByPrimaryKey(t);
    }



    /**
     * 通过主键集合批量删除
     * 数据库主键名必须为id
     * @param ids
     */
    public int deleteByIds(List<Integer> ids){
        Example example=Example.builder(getTypeArguement()).where(Sqls.custom().andIn("id",ids)).build();
        return mapper.deleteByExample(example);
    }



    /**
     * 更新
     * @param t
     * @return
     */
    public int update(T t){
       return  mapper.updateByPrimaryKeySelective(t);
    }

    public int batchUpdate(T record,Integer[] ids,Object properties){
        Example example=Example.builder(getTypeArguement()).where(Sqls.custom().andIn("id", Arrays.asList(ids))).build();
        return mapper.updateByExample(record,example);
    }

    /**
     * 查询一条数据
     * @param t
     * @return
     */
    public T queryOne(T t){
        return  mapper.selectOne(t);
    }

    /**
     * 通用查询指定字段service
     * @param where  查询条件
     * @param orderByField 排序字段
     * @param fields   实体类名
     * @return
     */
    public T queryOneByFiled(Sqls where,String orderByField, String ...fields){
         return (T) queryByFiledBase(null,null,where,orderByField,fields).get(0);
    }


    /**
     * 通过查询字段获取集合
     * @param where   where查询条件
     * @param orderByField  排序字段
     * @param fields 检索字段
     * @return List<T>
     */
    public List<T> queryListByFiled(Sqls where,String orderByField, String ...fields){
        return  queryByFiledBase(null,null,where,orderByField,fields);
    }

    /**
     * 通过字段查询分页
     * @param pageNo 起始页
     * @param pageSize  页大小
     * @param where  查询条件
     * @param orderByField  排序字段
     * @param fields  查询字段
     * @return pageInfo 分页对象
     */
    public PageInfo<T> queryListByPageAadFiled(Integer pageNo,Integer pageSize,Sqls where,String orderByField, String ...fields){
       return new PageInfo<T>(queryByFiledBase(pageNo,pageSize,where,orderByField,fields));
    }

    /**
     * 通过字段查询依托通用方法
     * @param pageNo 起始页
     * @param pageSize
     * @param where
     * @param orderByField
     * @param fields
     * @return
     */

    private List<T> queryByFiledBase(Integer pageNo,Integer pageSize,Sqls where,String orderByField, String ...fields){
        Example.Builder builder=null;
        if(null==fields||fields.length==0){
            //查询所有
            builder = Example.builder(getTypeArguement());

        }else{
            //查询指定字段
            builder= Example.builder(getTypeArguement())
                    .select(fields);
        }
        if(where!=null){
            builder=builder.where(where);
        }

        if(orderByField!=null){
            builder= builder
                    .orderByDesc(orderByField);
        }
        Example example=builder.build();

        if(pageNo!=null&&pageSize!=null) {
            PageHelper.startPage(pageNo, pageSize);    //分页插件
        }
        List list = getMapper().selectByExample(example);
        return  list;
    }

    /**
     * 查询多条结果
     * @param t 查询条件
     * @return
     */
    public List<T> queryList(T t){
       return mapper.select(t);
    }

    /**
     * 分页查询
     * @param t 条件
     * @param pageNo 当前页
     * @param pageSize  页大小
     * @return
     */
    public PageInfo<T> queryListByPage(T t,int pageNo,int pageSize){
         PageHelper.startPage(pageNo,pageSize);
         List<T> select = mapper.select(t);
         PageInfo<T> pageInfo = new PageInfo<>(select);
         return pageInfo;
    }




    /**
     * 反射实例
     * @param map
     * @return
     */
    public T newinstance(Map map){
        //自定义反射性能更高
        return (T) Bean2MapUtil.map2Bean(map,getTypeArguement());
//        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));
//        return  jsonObject.toJavaObject(getTypeArguement());
    }


    /**
     * 获取子类泛型类型
     * @return
     */
    public Class<T> getTypeArguement() {
         if(cache==null)
             cache= (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
         return  cache;
    }

    /**
     * 获取spring容器
     * @return
     */
    public ApplicationContext getApplicationContext(){
        return  SpringContextUtils.getApplicationContext();
    }

    protected Mapper getMapper(){
        return mapper;
    }
}

优化部分:

 1.  cache= (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

这里使用了缓存,缓存当前的子类泛型,不然每次都需要重新获取子类泛型结果,非常耗时,所以在这里进行了优化。


 2.   return (T) Bean2MapUtil.map2Bean(map,getTypeArguement());
//        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));
//        return  jsonObject.toJavaObject(getTypeArguement());

以前用的是alibabaFastJson的Map转PO的方法,但是发现该框架的性能基本上都集中于反射这里,后来通过自己写的Map转Bean的方法,用了两个工具 :objenesis,reflectasm,都是增强发射性能的。具博主测试,比原先方法性能提高了2.5倍其具体实现代码如下:


/**
 * bean与map互相转化工具
 * @author  dbw
 */
public class Bean2MapUtil {
    //高性能java实例化工具
    private final static Objenesis objenesis = new ObjenesisStd(true);
    private final static StringBuilder stringBuilder=new StringBuilder();
    //缓存reflectASM的反射字节集
    private final static ConcurrentHashMap<Class,MethodAccess> CONCURRENT_HASH_MAP=new ConcurrentHashMap<Class,MethodAccess>(16);

    /**
     * map转java bean工具类
     * @param map
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T>   T  map2Bean(Map<String,Object> map, Class<T> clazz){
        T instance = objenesis.newInstance(clazz);
        MethodAccess methodAccess = CONCURRENT_HASH_MAP.get(clazz);
        if(methodAccess==null){
            methodAccess=MethodAccess.get(clazz);
            CONCURRENT_HASH_MAP.putIfAbsent(clazz,methodAccess);
        }

        for(Map.Entry<String,Object> entry:map.entrySet()){
            String setMethodName = getSetMethodName(entry.getKey());
            int index = methodAccess.getIndex(setMethodName,entry.getValue().getClass());
            methodAccess.invoke(instance,index,entry.getValue());
        }
        return  instance;
    }

    /**
     * 
     * @Title: fristToUpperCase
     * @Description: 首字母变大写
     * @param @param str
     * @param @return 设定参数
     * @return String 返回类型
     * @since  1.0.0
     * @author dbw
     * @throws
     */
    private static String  fristToUpperCase(String str){
        return  str.substring(0,1).toUpperCase()+str.substring(1,str.length());
    }


    /**
     * 通过字段获取方法名字
     * @param filedName
     * @return
     */
    private static String getSetMethodName(String filedName){
        stringBuilder.setLength(0);
        return stringBuilder.append("set").append(fristToUpperCase(filedName)).toString();
    }
}

 其中两个工具用到的maven坐标如下:

<!-- Objenesis -->

<dependency>

<groupId>org.objenesis</groupId>

<artifactId>objenesis</artifactId>

<version>2.1</version>

</dependency>

<!--高性能反射工具-->

<dependency>

<groupId>com.esotericsoftware</groupId>

<artifactId>reflectasm</artifactId>

<version>1.11.0</version>

</dependency>

 后续等博主有时间了,再来写一写后续代码,博主也是小白,也是不断的学习,如果大家有什么需要指点的,积极在下面评论哦,我也会积极抽出耐心汲取大家宝贵的经验。谢谢啦!

猜你喜欢

转载自blog.csdn.net/s6056826a/article/details/84698305