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

入职新公司 选定了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  int saveEntity(String tableName,T t);
    
    @UpdateProvider(method = "updateEntity", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
    public  int updateEntity(String tableName,T t,Map params);
    
    @SelectProvider(method = "queryAllByParams", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
    public List> queryAllByParams(Class cls,String tableName,Map params);
    
    @SelectProvider(method = "queryPageByParams", type = com.huadi.xcx.dao.provider.MybaseProvider.class)
    public Page> queryPageByParams(Class cls,String tableName,Map 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  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  String updateEntity(String tableName,T t,Map 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 keys=params.keySet();
                        Iterator 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 params) {
        return queryPageByParams(cls,tableName,params);
    }
    
    public String queryPageByParams(Class cls,String tableName,Map params) {
        Field[] fields =cls.getDeclaredFields();
        return new SQL() {
            {
                SELECT("*");
                FROM(tableName);
                
                if(params !=null )
                {
                    Set keys=params.keySet();
                    Iterator 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  void saveEntity(String tableName,T t) {
        int row=mybaseDao.saveEntity(tableName, t);
    }
    
    public  void updateEntity(String tableName,T t,Map params) {
        int row=mybaseDao.updateEntity(tableName, t, params);
    }
    
    @SuppressWarnings("unchecked")
    public  List queryAllByParams(Class cls,String tableName,Map params) {
        List>  queryResult=mybaseDao.queryAllByParams(cls, tableName, params);
        List backResult = new ArrayList<>();
        Field[] fields = cls.getDeclaredFields();
        T nt;
        for(int i=0;i map =queryResult.get(i);
                StringBuffer sb = new StringBuffer();
                Set keys=map.keySet();
                Iterator 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  PageInfo queryPageByParams(Class cls,String tableName,Map params,int pageNum,int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page>  queryPage=mybaseDao.queryPageByParams(cls, tableName, params);
        PageInfo pageinfo =new PageInfo(queryPage);
        List> queryResult = pageinfo.getList();
        List resultList = new ArrayList<>();
        Field[] fields = cls.getDeclaredFields();
        T nt;
        for(int i=0;i map =queryResult.get(i);
                StringBuffer sb = new StringBuffer();
                Set keys=map.keySet();
                Iterator 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 selectOne(Class cls,String tableName,Map params) {
        PageHelper.startPage(1, 1);
        Page>  queryPage=mybaseDao.queryPageByParams(cls, tableName, params);
        PageInfo pageinfo =new PageInfo(queryPage);
        List> queryResult = pageinfo.getList();
        List resultList = new ArrayList<>();
        Field[] fields = cls.getDeclaredFields();
        T nt;
        for(int i=0;i map =queryResult.get(i);
                StringBuffer sb = new StringBuffer();
                Set keys=map.keySet();
                Iterator 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一样使用mybatis))