0
点赞
收藏
分享

微信扫一扫

MyBatis的mapper接口动态调用

1.问题来源

我们使用SpringMVC的时候,正常情况下调用一个mapper接口,我们需要在service里面先实例化一个mapper对象,然后调用对应的方法。现在有一种情况:有多个service,每个service里面都有一个selectAll()方法,执行相同的业务流程,唯一不同的就是方法内部调用的方法来自不同的mapper对象,这样我们就需要写很多相似的代码。

问题来了:有没有一种简单的方法,可以将这个类似的selectAll()方法从service里面抽取出来,做成一个公共的查询方法,调用的时候,只需要传入不同的mapper对象,就可以去执行整个方法呢?基于这个想法,我们可以使用以下方式来满足我们的要求:

1. 实现一个公共的mapper接口BaseDao.java,定义getList()方法;

2. 所有普通mapper都继承BaseDao接口

3. 实现一个公共的service类BaseService.java,实现selectAll()方法,将BaseDao作为参数传入。

4. 所有普通service都继承BaseService类

5. 普通service中调用这个selectAll()方法即可。

2.实现

2.1 创建BaseDao

将业务逻辑相似的方法都抽取出来

import java.util.List;

public interface BaseDao<T> {
	/**
	 * <h5>功能:根据条件获取全部信息</h5>
	 * 
	 * @param paramMap
	 * @return List<T>
	 */
	List<T> selectAll();
}

2.2 继承BaseDao

import org.apache.ibatis.annotations.Mapper;

import com.qfx.modules.common.dao.BaseDao;
import com.qfx.modules.system.entity.SysMenu;

@Mapper
public interface SysMenuMapper extends BaseDao<SysMenu>{

}

2.3 创建BaseService

这里要注意,抽取的公共方法selectAll()中,参数是mapper的父类BaseDao

import java.util.List;

import com.qfx.modules.common.dao.BaseDao;

public class BaseService<T> {

	/**
	 * 查询信息(这里抽取为公共方法)
	 * @param baseDao mapper实例
	 * @return
	 */
	protected List<T> selectAll(BaseDao<T> baseDao) {
        // 相同流程1略...

        // 动态调用不同mapper的selectAll()方法
        List<T> list = baseDao.selectAll();
        
        // 相同流程2略...

        return list;
    }
}

注意点:

MyBatis的mapper接口动态调用_java

2.4 继承BaseService

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.qfx.modules.common.service.BaseService;
import com.qfx.modules.system.dao.SysMenuMapper;
import com.qfx.modules.system.entity.SysMenu;

@Service
public class SysMenuSer extends BaseService<SysMenu> {

	@Autowired
	SysMenuMapper sysMenuMapper;

	/**
	 * 查询菜单信息
	 */
	public List<SysMenu> getList() {
		// 调用BaseService中的selectAll()方法
		return selectAll(sysMenuMapper);
	}
}

重点关注这里:

MyBatis的mapper接口动态调用_java_02

2.5 测试

至此,mapper接口动态调用的功能已经实现,我们执行一下单元测试,看看是否成功。

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.alibaba.fastjson.JSONObject;
import com.qfx.modules.system.entity.SysMenu;
import com.qfx.modules.system.service.impl.SysMenuSer;

@SpringBootTest
class RunAppTests {
	
	@Autowired
	SysMenuSer sysMenuSer;
	
	@Test
	void test() {
		List<SysMenu> sysMenuList = sysMenuSer.getList();
		for (SysMenu sysMenu : sysMenuList) {
			System.out.println(JSONObject.toJSONString(sysMenu));
		}
	}
}

执行结果:正常输出,到这里就结束了,其他业务继续正常编写即可。

MyBatis的mapper接口动态调用_java_03

3.扩展(抽取分页方法)

这里将pagehelper分页的方法抽取为一个公共的方法,完整代码如下:

3.1 创建BaseDao

创建公共接口BaseDao.java

import java.util.List;
import java.util.Map;

public interface BaseDao<T> {
	/**
	 * <h5>功能:根据条件获取全部信息</h5>
	 * 
	 * @param paramMap
	 * @return List<T>
	 */
	List<T> selectAll(Map<String, Object> paramMap);
}

3.2 继承BaseDao

Mapper接口继承BaseDao接口

import com.qfx.modules.common.dao.BaseDao;
import com.qfx.modules.system.entity.SysMenu;

public interface SysMenuMapper extends BaseDao<SysMenu>{

}

3.3 创建BaseService

封装了 获取从request中传递过来的参数信息获取分页信息分页查询信息等公共方法。

import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qfx.modules.common.dao.BaseDao;

public class BaseService<T> {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	protected static String CURRENT_PAGE_NAME = "page";
	protected static String PAGE_SIZE_NAME = "limit";

	@Autowired
	protected HttpServletRequest request;

	/**
	 * <h5>功能:获取从request中传递过来的参数信息</h5>
	 * 
	 * @return Map<String, Object>
	 */
	protected Map<String, Object> getMaps() {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		Enumeration<String> enume = request.getParameterNames();
		while (enume.hasMoreElements()) {
			String key = (String) enume.nextElement();
			String[] values = request.getParameterValues(key);
			paramMap.put(key, values.length == 1 ? request.getParameter(key).trim() : values);
		}

		return paramMap;
	}

	/**
	 * @功能描述:获取分页信息
	 *
	 * @param map
	 * @return
	 *
	 * @作者:zhangpj @创建时间:2018年3月23日
	 */
	protected Page<T> getPage(Map<String, Object> map) {
		int pageNum = 1;
		int pageSize = 10;
		if (map.containsKey(CURRENT_PAGE_NAME) && !"".equals(map.get(CURRENT_PAGE_NAME))) {
			pageNum = Integer.parseInt((String) map.get(CURRENT_PAGE_NAME));
		}
		if (map.containsKey(PAGE_SIZE_NAME) && !"".equals(map.get(PAGE_SIZE_NAME))) {
			pageSize = Integer.parseInt((String) map.get(PAGE_SIZE_NAME));
		}
		Page<T> page = new Page<>(pageNum, pageSize);
		return page;
	}
	
	/**
	 * 分页查询信息(这里抽取为公共方法)
	 * @param baseDao
	 * @return
	 */
	protected Map<String, Object> selectAll(BaseDao<T> baseDao) {
        Map<String, Object> paramMap = getMaps();
        Page<T> page = getPage(paramMap);
        PageHelper.startPage(page.getPageNum(), page.getPageSize());

        List<T> list = baseDao.selectAll(paramMap);
        PageInfo<T> pageInfo = new PageInfo<>(list);
        long total = pageInfo.getTotal();

        Map<String, Object> map = new HashMap<>();
        map.put("code", 0);
        map.put("count", total);
        map.put("data", pageInfo.getList());

        return map;
    }
}

3.4 继承BaseService

继承BaseService类,直接调用其中的方法即可

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.qfx.modules.common.service.BaseService;
import com.qfx.modules.system.dao.SysMenuMapper;
import com.qfx.modules.system.entity.SysMenu;

@Service
public class SysMenuSerImpl extends BaseService<SysMenu> {

	@Autowired
	SysMenuMapper sysMenuMapper;

	/**
	 * 分页查询菜单信息(抽取为公共方法)
	 */
	public Map<String, Object> getList() {
		return selectAll(sysMenuMapper);
	}
}

重点关注这里:

MyBatis的mapper接口动态调用_MyBatis_04

3.5 Controller

正常编写控制器即可

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.qfx.modules.system.service.impl.SysMenuSerImpl;

@RestController
@RequestMapping("sys/menu")
public class SysMenuCtl {
	@Autowired
	SysMenuSerImpl sysMenuSerImpl;
	
	/**
	 * 分页查询菜单信息
	 * @return
	 */
	@RequestMapping("list")
	public Map<String,Object> list(){
		return sysMenuSerImpl.getList();
	}
}

3.6 测试

http://127.0.0.1:8081/sys/menu/list?page=2&limit=2

MyBatis的mapper接口动态调用_MyBatis_05

http://127.0.0.1:8081/sys/menu/list?page=6&limit=2

MyBatis的mapper接口动态调用_java_06

举报

相关推荐

0 条评论