mybaties封装

mybaties封装

一、 流程图

在这里插入图片描述

二、 好处

  1. 方便接口功能扩展
  2. 减少开发代码写sql语句的麻烦
  3. 代码整洁清晰且易于维护

三、 案例(已一个复杂的查询为案例,代码只给出所需要的代码)

3.1 代码入口

	package com.apiserver.producer.system;
	
	
	import com.apiserver.data.mybatis.util.SortConstants;
	import com.apiserver.model.system.entity.SUsers;
	import com.apiserver.producer.system.service.UsersService;
	import org.junit.Test;
	import org.junit.runner.RunWith;
	import org.springframework.beans.factory.annotation.Autowired;
	import org.springframework.boot.test.context.SpringBootTest;
	import org.springframework.test.context.junit4.SpringRunner;
	
	import java.util.*;
	
	@RunWith(SpringRunner.class)
	@SpringBootTest
	public class ProducerSystemApplicationTests {
	    @Autowired
	  public    UsersService usersService;
	
	
	    @Test
	    public void selectAllByOtherKey(){
	
	        //一般查询的sql
	        SUsers sUser = SUsers.builder()
	                .id(252405769423826944L)
	                .chineseName("露西")
	                .build();
	
	        //排序
	        LinkedHashMap<String,String> sortrMap=new LinkedHashMap<>();
	        sortrMap.put("chineseName", SortConstants.DESC);
	        sortrMap.put("id", SortConstants.ASC);
	
	        //like 查询
	        Map<String,Object> likeQueryMap=new HashMap<>();
	        likeQueryMap.put("pwd","11111");
	        likeQueryMap.put("email","324234@qq.com");
	
	        //一个字段多个值的查询
	        Map<String,List<Object>> arrayQueryMap=new HashMap<>();
	        List<Object> list1=new ArrayList<>();
	        list1.add(111);
	        list1.add(222);
	        arrayQueryMap.put("education",list1);
	
	        List<Object> list2=new ArrayList<>();
	        list2.add(333);
	        list2.add(444);
	        arrayQueryMap.put("age",list2);
	
	        List<SUsers> sUsers =usersService.selectAllByOtherKey(sUser,likeQueryMap,arrayQueryMap,sortrMap);
	
	        System.out.println(sUsers);
	
	    }
	
	
	}

3.2 上面通过注解加载UsersService类,那么加载UsersService类做了什么呢?

	public interface UsersService extends BaseService<SUsers> {
	}


	@Repository
	public class UsersServiceImpl extends BaseServiceImpl<UsersMapper,SUsers> implements UsersService {
	
	}

3.3 上面我们看到UsersService继承BaseService,UsersServiceImpl继承BaseServiceImpl,那么BaseService和BaseServiceImpl做了什么?

	/**
	 * @Author feizhou
	 * @Description  基本方法封装
	 * @Date 下午 10:18 2019/10/10 0010
	 * @Param 
	 * @return 
	 **/
	
	public interface BaseService<M>    {
		/**
		 * @Author feizhou
		 * @Description 返回排序列表,支持模糊查询,支持1属性多个值的查询
		 * @Date 下午 11:22 2019/10/11 0011
		 * @Param [m, sortMap, likePropertyNameList, arrayQueryMap]
		 * @return java.util.List<M>
		 **/
		
		List<M> selectAllByOtherKey(M m,Map<String,Object> likeQueryMap,Map<String,List<Object>> arrayQueryMap,LinkedHashMap<String,String> sortMap);
	}
	




	/**
	 * @Author feizhou
	 * @Description 基本方法封装
	 * @Date 下午 10:19 2019/10/10 0010
	 * @Param
	 * @return
	 **/
	@Slf4j
	public abstract class BaseServiceImpl<D extends BaseMapper<M>, M> implements BaseService<M> {
	
	    protected D dao;
	
	    @Autowired
	    public void setDao(D dao) {
	        this.dao = dao;
	    }
	
	    private Class<M> entityClass;
	
	    @SuppressWarnings("unchecked")
	    @PostConstruct//构造完成执行的方法
	    public void init() {
	        entityClass = (Class<M>) ((ParameterizedType) getClass()
	                .getGenericSuperclass()).getActualTypeArguments()[1];
	    }
	
	    @Override
	    public List<M> selectAllByOtherKey(M m, Map<String, Object> likeQueryMap, Map<String, List<Object>> arrayQueryMap, LinkedHashMap<String, String> sortMap) {
	        return dao.selectAllByOtherKey(m, likeQueryMap, arrayQueryMap, sortMap);
	    }
	
	}

BaseServiceImpl

  1. 我们可以看到,该类提供protected D(BaseMapper) dao, 子类通过继承可以使用该dao,也就是说UsersServiceImpl可以使用该dao。

  2. 该dao使用注解的方式注入

  3. @PostConstruct注解修饰init(),表示构造完成后执行init方法,init方法是为了获取当前类的类对象。

        public void init() {
     			entityClass = (Class<M>) ((ParameterizedType) getClass()
                     .getGenericSuperclass()).getActualTypeArguments()[1];	
         }
    
     	代码分解如下-------
    
     	//当前对象的直接超类的 Type  
     	Type  superclass =getClass().getGenericSuperclass();
     	
     	//参数化类型  
     	ParameterizedType  parameterizedType=(ParameterizedType)superclass;
     			
     	//返回表示此类型实际类型参数的 Type 对象的数组的第一个元素
     	Type type=parameterizedType.getGenericSuperclass()).getActualTypeArguments()[1];
     	//转换类对象
     	(Class<M>)	 entityClass = (Class<M>)type
    
  4. 通过3可以获取到,UsersServiceImpl还有一个entityClass(SUsers.class),也就是说,每一个业务实现类,都有一个自己的类对象。

3.4 通过上面,我们已经将访问service的类和类构造讲完了。

3.5 现在我们介绍下 usersService.selectAllByOtherKey(sUser,likeQueryMap,arrayQueryMap,sortrMap)代码流程

  1. selectAllByOtherKey实际如下截图
    在这里插入图片描述
    在这里插入图片描述

  2. 通过1我们知道,selectAllByOtherKey实际调用的是SelProvider类的selectAllByOtherKey方法
    /**
    * @author hs
    * @description 生成mybatis动态sql
    * @date 2016年12月30日下午4:59:00
    */
    @Slf4j
    public class SelProvider extends Provider {

         /**
          * @return java.lang.String
          * @Author feizhou
          * @Description 返回排序列表,支持模糊查询,支持一属性,多个值的查询
          * @Date 下午 10:33 2019/10/10 0010
          * @Param [t]
          **/
     
         public <M> String selectAllByOtherKey(Map<String, Object> param) {
     
     
             M m = (M) param.get("m");
             LinkedHashMap<String, String> sortMap = (LinkedHashMap<String, String>) param.get("sortMap");
             Map<String, Object> likeQueryMap = (Map<String, Object>) param.get("likeQueryMap");
             Map<String, List<Object>> arrayQueryMap = (Map<String, List<Object>>) param.get("arrayQueryMap");
     
             EntityTable entity = EntityUtil.getEntityTable(m);
     
             SQL sql = new SQL()
                     .SELECT(entity.getSqlColumns())
                     .FROM(entity.getTableName())
                     .WHERE("1 = 1");
     
             getWhere(m, sql, entity);
             getLikeWhere(likeQueryMap, sql, entity);
             getWhereForIn(arrayQueryMap, sql, entity);
             getOrderSql(sortMap, sql, entity);
             return sql.toString();
         }
     
     }
    

3.6 selectAllByOtherKey代码解析

EntityUtil.getEntityTable(m)
	/**
	 * 获取表对象
	 *
	 * @return
	 */
	public static EntityTable getEntityTable(Object obj) {
		EntityTable entityTable = getEntityTableWithoutParams(obj);
		return entityTable;
	}


	-----获取表对象
	/**
	 * @Author feizhou
	 * @Description 获取实体的信息
	 * @Date 下午 4:45 2019/10/8 0008
	 * @Param [obj]
	 * @return com.apiserver.data.mybatis.model.EntityTable
	 **/
	
	public static EntityTable getEntityTableWithoutParams(Object obj) {
		//obj 就是传入的泛型M,也就是SUsers的类对象
		//获取类对象
		Class<?> entityClass = obj.getClass();
		//获取当前类对象的实体表信息
		EntityTable entityTable = entityTableMap.get(entityClass);
		if (entityTable == null){//没有获取到返回
			initEntityNameMap(entityClass);
		}
		//再查一次,因为第一次可能entityTable==null.
		entityTable = entityTableMap.get(entityClass);
		return entityTable;
	}
	

	---初始化实体属性
	/**
	 * @Author feizhou
	 * @Description 初始化实体属性
	 * @Date 下午 1:27 2019/10/9 0009
	 * @Param [entityClass]
	 * @return void
	 **/
	
	private synchronized static void initEntityNameMap(Class<?> entityClass) {
	
		//如果实体存在,就不初始化
		if (entityTableMap.get(entityClass) != null){
			return;
		}
	
		Style style = Style.camelhumpAndLowercase;// 默认驼峰命名法
	
		// style,该注解优先于全局配置
		if (entityClass.isAnnotationPresent(NameStyle.class)){
			style = entityClass.getAnnotation(NameStyle.class).value();
		}
	
		// 创建并缓存EntityTable
		EntityTable entityTable = new EntityTable(entityClass);
	
		//实体类需要table注解
		if (!entityClass.isAnnotationPresent(Table.class)){
			throw new DataException(ErrCode.table_Not_Exist);
		}
	
	
		Table table = entityClass.getAnnotation(Table.class);
		//表名存在的情况
		if (!table.name().equals("")) {
			entityTable.setTableName(table.name());
		}else {
			String tableName = StyleUtil.convertByStyle(entityClass.getSimpleName(), style);
			entityTable.setTableName(table.prefix()+tableName);
		}
	
		//字段转换方式
		entityTable.setStyle(style);
	
	 	// 处理所有列
	
		List<ColumnProperty> columnProperties = ColumnPropertyUtil.getColumnProperties(entityClass, style);
	
	
		buildEntityTable(entityTable,columnProperties);
	
	
		entityTableMap.put(entityClass, entityTable);
	}

其中entityTableMap定义

	private static final Map<Class<?>, EntityTable> entityTableMap = new ConcurrentHashMap<>();

buildEntityTable方法

	/**
	 * @Author feizhou
	 * @Description 构建主键EntityTable
	 * @Date 下午 3:23 2019/10/9 0009
	 * @Param [entityTable, columnProperties]
	 * @return void
	 **/
	
	private static void buildEntityTable(EntityTable entityTable, List<ColumnProperty> columnProperties) {
	
		StringBuffer sqlColumns=new StringBuffer();
	
		Map<String, String> propertyColumn=new HashMap<>();
	
	
		for (ColumnProperty columnProperty : columnProperties) {
	
			String columnName = columnProperty.getColumnName();
			String propertyName = columnProperty.getPropertyName();
	
	
			sqlColumns.append(columnName);
			sqlColumns.append(",");
	
	
			//构建主键
			if(columnProperty.getIsPK()){
				entityTable.setPKColumn(columnName);
				entityTable.setPKProperty(propertyName);
				entityTable.setIdStrategy(columnProperty.getIdStrategy());
			}
	
			propertyColumn.put(propertyName,columnName);
		}
	
		entityTable.setPropertyColumn(propertyColumn);
	
		//sql查询列
		if(sqlColumns.length()>0){
			entityTable.setSqlColumns(sqlColumns.substring(0,sqlColumns.length()-1));
		}
	}

getColumnProperties

	/**
	 * @Author feizhou
	 * @Description ColumnProperty工具类
	 * @Date 下午 2:25 2019/10/9 0009
	 * @Param
	 * @return
	 **/
	
	public class ColumnPropertyUtil {
	
	    private static final IColumnPropertyHelper columnPropertyHelper;
	
	    private static final String JAVA_VERSION = System
	            .getProperty("java.version");
	
	    static {
	        if (JAVA_VERSION.contains("1.8.")) {
	            columnPropertyHelper = new Jdk8ColumnPropertyHelper();
	        } else {
	            //目前先不处理
	            columnPropertyHelper = new Jdk8ColumnPropertyHelper();
	        }
	    }
	
	    /**
	     * 获取ColumnProperty
	     *
	     * @param entityClass
	     * @return
	     */
	    public static List<ColumnProperty> getColumnProperties(Class<?> entityClass, Style style) {
	        return columnPropertyHelper.getColumnProperties(entityClass, style);
	    }
	
	
	    /**
	     * Field接口
	     */
	    interface IColumnPropertyHelper {
	
	        /**
	         * 获取ColumnPropertie
	         *
	         * @param entityClass
	         * @return
	         */
	        List<ColumnProperty> getColumnProperties(Class<?> entityClass, Style style);
	
	
	    }
	
	    /**
	     * 支持jdk8
	     */
	    static class Jdk8ColumnPropertyHelper implements IColumnPropertyHelper {
	
	        /**
	         * 获取全部的getColumnProperties
	         *
	         * @param entityClass
	         * @return
	         */
	        public List<ColumnProperty> getColumnProperties(Class<?> entityClass, Style style) {
	
	            return _getColumnProperties(entityClass, null, null, style);
	        }
	
	        /**
	         * @return java.util.List<com.apiserver.data.mybatis.model.ColumnProperty>
	         * @Author feizhou
	         * @Description 获取全部的ColumnPropertie
	         * @Date 下午 1:41 2019/10/9 0009
	         * @Param [entityClass, list, level]
	         **/
	
	        private List<ColumnProperty> _getColumnProperties(Class<?> entityClass, List<ColumnProperty> list, Integer level, Style style) {
	
	            if (list == null) {
	                list = new ArrayList<ColumnProperty>();
	            }
	            if (level == null) {
	                level = 0;
	            }
	            //Object就直接返回
	            if (entityClass.equals(Object.class)) {
	                return list;
	            }
	
	            //获取所有的字段
	            Field[] fields = entityClass.getDeclaredFields();
	            int index = 0;
	
	            for (int i = 0; i < fields.length; i++) {
	
	                Field field = fields[i];
	                //排除构造参数this
	                if (field.getName().contains("this$0")) {
	                    continue;
	                }
	
	                // 排除静态字段
	                if (!Modifier.isStatic(field.getModifiers())) {
	
	                    ColumnProperty columnProperty = getColumnProperty(field, style);
	
	                    if (level.intValue() != 0) {
	                        // 将父类的字段放在前面
	                        list.add(index, columnProperty);
	                        index++;
	                    } else {
	                        list.add(columnProperty);
	                    }
	                }
	            }
	
	
	            //构建父类的字段,迭代
	            Class<?> superClass = entityClass.getSuperclass();
	            if (superClass != null && !superClass.equals(Object.class)
	                    && (superClass.isAnnotationPresent(Entity.class)
	                    || (!Map.class.isAssignableFrom(superClass) && !Collection.class.isAssignableFrom(superClass)))) {
	
	                return _getColumnProperties(entityClass.getSuperclass(), list, ++level, style);
	
	            }
	            return list;
	        }
	
	        /**
	         * @return void
	         * @Author feizhou
	         * @Description 获取ColumnProperty
	         * @Date 下午 1:38 2019/10/9 0009
	         * @Param [field]
	         **/
	
	        private ColumnProperty getColumnProperty(Field field, Style style) {
	
	            String propertyName = field.getName();
	            //数据库列名
	            String columnName = propertyName;
	
	            Class<?> javaType = field.getType();
	            Boolean isPK = false;
	            Boolean isTransient = false;
	            IdStrategy idStrategy=null;
	
	            //  Transient注解
	            if (field.isAnnotationPresent(Transient.class)) {
	                isTransient = true;
	            }
	
	            // 主键
	            if (field.isAnnotationPresent(Id.class)) {
	                isPK = true;
	                idStrategy=field.getAnnotation(Id.class).value();
	            }
	
	            //数据库列名
	            if (field.isAnnotationPresent(Column.class)) {
	                Column column = field.getAnnotation(Column.class);
	                columnName = column.name();
	            } else {
	                columnName = StyleUtil.convertByStyle(columnName, style);
	            }
	
	
	            return new ColumnProperty(columnName, propertyName, isPK, isTransient, null, javaType,idStrategy);
	        }
	
	    }
	
	
	}

3.7 下面给出2个重要的类

	public class EntityTable {
	
	    private String sqlColumns;
	
	    private String tableName;
	
	    private Class<?> entityClass;
	    //字段转换方式
	    private Style style;
	
	    //主键
	    private String PKColumn;
	    //主键
	    private String PKProperty;
	    //主键策略
	    private IdStrategy idStrategy;
	    //key:属性名, value:数据库列名
	    private Map<String, String> propertyColumn;
	    public EntityTable(Class<?> entityClass) {
	        super();
	        this.entityClass = entityClass;
	    }
	
	}
	

	----
	public class ColumnProperty {
    //数据库列名称
    private String columnName;
    //实体属性名称
    private String propertyName;
    //是否主键
    private Boolean isPK;
    //是否过滤字段
    private Boolean isTransient;
    //值
    private Object value;
    //实体字段对应的类型
    private Class<?> javaType;
    //实体字段对应的类型
    private IdStrategy idStrategy;
	}

3.8 后面通过实体entity解析sql

    EntityTable entity = EntityUtil.getEntityTable(m);

    SQL sql = new SQL()
            .SELECT(entity.getSqlColumns())
            .FROM(entity.getTableName())
            .WHERE("1 = 1");

    getWhere(m, sql, entity);
    getLikeWhere(likeQueryMap, sql, entity);
    getWhereForIn(arrayQueryMap, sql, entity);
    getOrderSql(sortMap, sql, entity); 


	-- 获取where语句,解析出来和mybaties的xml配置里面写的是一样的。
    protected <M> SQL getWhere(M m, SQL sql, EntityTable entity) {

        Map<String, Object> queryMap = MapTools.objectToMapNotNull(m);

        for (Map.Entry<String, Object> entry : queryMap.entrySet()) {
            sql = sql.WHERE(entity.getPropertyColumn().get(entry.getKey()) + "=#{m." + entry.getKey() + "}");
        }
        return sql;
    }

四、代码位置

https://gitee.com/DanShenGuiZu/GongKaiZiYuan/tree/master/mrgo-api

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值