美文网首页
mybatis全自动ORM二次封装(像hibernate一样使用

mybatis全自动ORM二次封装(像hibernate一样使用

作者: 水表学Java | 来源:发表于2019-01-31 23:12 被阅读0次

    入职新公司 选定了mybatis作为orm框架,mybatis的好处简单明了直接写sql语句就行,但是对于已经习惯了hibernate的我来说mybatis每个单表查询都要新建接口和xml映射文件就有点麻烦了,我在想能不能和hibernate一样直接调用save(),update(),query()方法就直接能执行dml语句呢,于是尝试封装mybatis做一个基础的mapper。

    在这里使用mybatis java api的 provider动态执行sql

    basemapper接口

    import java.util.Map;
    
    import org.apache.ibatis.annotations.InsertProvider;
    import org.apache.ibatis.annotations.SelectProvider;
    import org.apache.ibatis.annotations.UpdateProvider;
    
    import com.github.pagehelper.Page;
    
    /**
     * 通用mapper
     * @author zwt
     *
     */
    public interface MybaseMapper {
        
    
        @InsertProvider(method = "saveEntity", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
        public <T> int saveEntity(String tableName,T t);
        
        @UpdateProvider(method = "updateEntity", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
        public <T> int updateEntity(String tableName,T t,Map<String,Object> params);
        
        @SelectProvider(method = "queryAllByParams", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
        public List<Map<String,Object>> queryAllByParams(Class<?> cls,String tableName,Map<String,Object> params);
        
        @SelectProvider(method = "queryPageByParams", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
        public Page<Map<String,Object>> queryPageByParams(Class<?> cls,String tableName,Map<String,Object> params);
    }
    
    

    mapper对应的provider

    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    import org.apache.ibatis.jdbc.SQL;
    
    import com.huadi.xcx.common.util.FieldUtils;
    
    /**
     * 通用provider
     * @author zwt
     *
     */
    public class MybaseProvider{
        
        public <T> String saveEntity(String tableName,T t) throws Exception {
            Field[] fields =t.getClass().getDeclaredFields();
            return new SQL(){
                    {
                        INSERT_INTO(tableName);
                        for(Field f:fields) {
                            f.setAccessible(true);
                            String key=f.getName();
                            Object value =f.get(t);
                            if(value!=null) {
                                VALUES(f.getName(), "#{t."+key+"}");
                            }
                        }
                    }
                }.toString();
        }
        
        public <T> String updateEntity(String tableName,T t,Map<String,Object> params) throws Exception {
            if(params==null || params.keySet().size()<1)
            {
                throw new Exception("updateEntity 方法必须有条件参数");
            }
            
            Field[] fields =t.getClass().getDeclaredFields();
            return new SQL(){
                    {
                        UPDATE(tableName);
                        for(Field f:fields) {
                            f.setAccessible(true);
                            String key=f.getName();
                            Object value =f.get(t);
                            if(value!=null) {
                                SET(f.getName()+" = #{t."+key+"}");
                            }
                        }
                        
                        if(params !=null )
                        {
                            Set<String> keys=params.keySet();
                            Iterator<String> it=keys.iterator();
                            while(it.hasNext()) {
                                String key= it.next();
                                String filedName=FieldUtils.UnderlineToHump(key);
                                for(Field f:fields) {
                                    if(filedName.equals(f.getName()))
                                    {
                                        if(String.class.toString().equals(f.getGenericType().toString()))
                                        {
                                            WHERE("to_char("+key+") = #{params."+key+"}");
                                        }else
                                        {
                                            WHERE(key+" = #{params."+key+"}");
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }.toString();
        }
        
        public String queryAllByParams(Class<?> cls,String tableName,Map<String,Object> params) {
            return queryPageByParams(cls,tableName,params);
        }
        
        public String queryPageByParams(Class<?> cls,String tableName,Map<String,Object> params) {
            Field[] fields =cls.getDeclaredFields();
            return new SQL() {
                {
                    SELECT("*");
                    FROM(tableName);
                    
                    if(params !=null )
                    {
                        Set<String> keys=params.keySet();
                        Iterator<String> it=keys.iterator();
                        while(it.hasNext()) {
                            String key= it.next();
                            String filedName=FieldUtils.UnderlineToHump(key);
                            for(Field f:fields) {
                                if(filedName.equals(f.getName()))
                                {
                                    if(String.class.toString().equals(f.getGenericType().toString()))
                                    {
                                        WHERE("to_char("+key+") = #{params."+key+"}");
                                    }else
                                    {
                                        WHERE(key+" = #{params."+key+"}");
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }.toString();
        }
    
    }
    
    

    此时baseMapper 相当于传统意义的baseDao,但是由于查询出来的是resultSet 集合并不能直接使用,如果要使用对象还需要手动转型,十分麻烦,如何才能和hibernate一样查出来的直接是java对象呢

    此时便定义一个baseService提供基础增删该查功能
    需要注意的是数据库类型与javabean类型不同需要转型 此处暂时只转了BigDecimal与CLOB型

    import java.lang.reflect.Method;
    import java.lang.reflect.Type;
    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.github.pagehelper.Page;
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.huadi.xcx.common.util.FieldUtils;
    import com.huadi.xcx.dao.MybaseMapper;
    
    import oracle.sql.CLOB;
    /**
     * 通用增删改查方法
     * @author zwt
     *
     */
    
    @Service("MyBaseService")
    public class MyBaseService {
        
        @Autowired
        private MybaseMapper mybaseDao;
        
        //保存暂时还不支持带出自增主键 有需求可以以后添加
        public <T> void saveEntity(String tableName,T t) {
            int row=mybaseDao.saveEntity(tableName, t);
        }
        
        public <T> void updateEntity(String tableName,T t,Map<String,Object> params) {
            int row=mybaseDao.updateEntity(tableName, t, params);
        }
        
        @SuppressWarnings("unchecked")
        public <T> List<T> queryAllByParams(Class<?> cls,String tableName,Map<String,Object> params) {
            List<Map<String,Object>>  queryResult=mybaseDao.queryAllByParams(cls, tableName, params);
            List<T> backResult = new ArrayList<>();
            Field[] fields = cls.getDeclaredFields();
            T nt;
            for(int i=0;i<queryResult.size();i++)
            {
                try {
                    nt=(T) cls.newInstance();
                    Map<String,Object> map =queryResult.get(i);
                    StringBuffer sb = new StringBuffer();
                    Set<String> keys=map.keySet();
                    Iterator<String> it =keys.iterator();
                    while(it.hasNext()) {
                        String key=it.next();
                        String fieldName=FieldUtils.UnderlineToHump(key);
                        Object value =map.get(key);
                        for(Field f:fields) {
                            if(fieldName.equals(f.getName())) {
                                f.setAccessible(true);
                                //需要转型
                                if(BigDecimal.class.toString().equals(value.getClass().toString())) {
                                    Type type=f.getGenericType();
                                    Class fieldClass =Class.forName(type.getTypeName());
                                    Method method=fieldClass.getMethod("valueOf",String.class);
                                    value=method.invoke(value, value.toString());
                                    f.set(nt, value);
                                }else if(CLOB.class.toString().equals(value.getClass().toString())) {
                                    f.set(nt, FieldUtils.ClobToString((CLOB)value));
                                }
                                else {
                                    f.set(nt, value);
                                }
                                break;
                            }
                        }
                    }
                    backResult.add(nt);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            return backResult;
        }
        
        @SuppressWarnings("unchecked")
        public <T> PageInfo<T> queryPageByParams(Class<?> cls,String tableName,Map<String,Object> params,int pageNum,int pageSize) {
            PageHelper.startPage(pageNum, pageSize);
            Page<Map<String,Object>>  queryPage=mybaseDao.queryPageByParams(cls, tableName, params);
            PageInfo pageinfo =new PageInfo(queryPage);
            List<Map<String,Object>> queryResult = pageinfo.getList();
            List<T> resultList = new ArrayList<>();
            Field[] fields = cls.getDeclaredFields();
            T nt;
            for(int i=0;i<queryResult.size();i++)
            {
                try {
                    nt=(T) cls.newInstance();
                    Map<String,Object> map =queryResult.get(i);
                    StringBuffer sb = new StringBuffer();
                    Set<String> keys=map.keySet();
                    Iterator<String> it =keys.iterator();
                    while(it.hasNext()) {
                        String key=it.next();
                        String fieldName=FieldUtils.UnderlineToHump(key);
                        Object value =map.get(key);
                        for(Field f:fields) {
                            if(fieldName.equals(f.getName())) {
                                f.setAccessible(true);
                                //需要转型
                                if(BigDecimal.class.toString().equals(value.getClass().toString())) {
                                    Type type=f.getGenericType();
                                    Class fieldClass =Class.forName(type.getTypeName());
                                    Method method=fieldClass.getMethod("valueOf",String.class);
                                    value=method.invoke(value, value.toString());
                                    f.set(nt, value);
                                }else if(CLOB.class.toString().equals(value.getClass().toString())) {
                                    f.set(nt, FieldUtils.ClobToString((CLOB)value));
                                }
                                else {
                                    f.set(nt, value);
                                }
                                break;
                            }
                        }
                    }
                    resultList.add(nt);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            pageinfo.setList(resultList);
            return pageinfo;
        }
    
        @SuppressWarnings("unchecked")
        public <T> T selectOne(Class<?> cls,String tableName,Map<String,Object> params) {
            PageHelper.startPage(1, 1);
            Page<Map<String,Object>>  queryPage=mybaseDao.queryPageByParams(cls, tableName, params);
            PageInfo pageinfo =new PageInfo(queryPage);
            List<Map<String,Object>> queryResult = pageinfo.getList();
            List<T> resultList = new ArrayList<>();
            Field[] fields = cls.getDeclaredFields();
            T nt;
            for(int i=0;i<queryResult.size();i++)
            {
                try {
                    nt=(T) cls.newInstance();
                    Map<String,Object> map =queryResult.get(i);
                    StringBuffer sb = new StringBuffer();
                    Set<String> keys=map.keySet();
                    Iterator<String> it =keys.iterator();
                    while(it.hasNext()) {
                        String key=it.next();
                        String fieldName=FieldUtils.UnderlineToHump(key);
                        Object value =map.get(key);
                        for(Field f:fields) {
                            if(fieldName.equals(f.getName())) {
                                f.setAccessible(true);
                                //需要转型
                                if(BigDecimal.class.toString().equals(value.getClass().toString())) {
                                    Type type=f.getGenericType();
                                    Class fieldClass =Class.forName(type.getTypeName());
                                    Method method=fieldClass.getMethod("valueOf",String.class);
                                    value=method.invoke(value, value.toString());
                                    f.set(nt, value);
                                }else if(CLOB.class.toString().equals(value.getClass().toString())) {
                                    f.set(nt, FieldUtils.ClobToString((CLOB)value));
                                }
                                else {
                                    f.set(nt, value);
                                }
                                break;
                            }
                        }
                    }
                    return nt;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    
    }
    

    有了这个baseService 便可以和hibernate一样查询出来直接是想要的对象了

    思考:由于大量使用反射会不会造成性能问题,而且是基于mybatis的二次封装相当于多了一倍的结果对象,会消耗一倍的内存。
    根据POJO类生成数据库表也可以写一套简易的,以后有空再写。

    相关文章

      网友评论

          本文标题:mybatis全自动ORM二次封装(像hibernate一样使用

          本文链接:https://www.haomeiwen.com/subject/okzlsqtx.html