通常情况下,我们之间调用mapper,spring会为我们注入其实现,很方便,mybatis也提供了一个generator供我们生成bean、dao接口等。但是总有一种感觉叫不爽,感觉除了bean和mapping.xml之外,dao接口有着共性,没有必要每一个都写一遍,共性的东东要提出来。下面就说一下怎么利用面向接口的思想进行提炼!
1、bean接口IModel
package com.jdw.bean; /** * 所有的bean都要implements该接口 * 至于原因,且往后看! * @author Administrator * */ public interface IModel { }
2、实现IModel接口的Category
package com.jdw.bean; /** * 实现了IModel接口的Category Bean * @author Administrator * */ public class Category implements IModel { private Integer cId; private String cName; private Boolean hot; public Integer getCId() { return cId; } public void setCId(Integer cId) { this.cId = cId; } public String getCName() { return cName; } public void setCName(String cName) { this.cName = cName == null ? null : cName.trim(); } public Boolean getHot() { return hot; } public void setHot(Boolean hot) { this.hot = hot; } @Override public String toString() { return "Category [cId=" + cId + ", cName=" + cName + ", hot=" + hot + "]"; } }
3、dao接口的接口IMapper
package com.jdw.dao; import com.jdw.bean.IModel; /** * mybatis mapper都要extends该接口 * @author Administrator * * @param <M> */ public interface IMapper<M extends IModel>{ int deleteByPrimaryKey(Integer id); int insert(M model); int insertSelective(M model); M selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(M model); int updateByPrimaryKey(M model); }
4、继承了IMapper接口的Category接口
package com.jdw.dao; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Param; import com.jdw.bean.Category; /** * 继承了IMapper接口的CategoryMapper接口 * 可以看出,现在只需要在这里面写特有的接口了,共性的接口放到IMapper里面了 * @author Administrator * */ public interface CategoryMapper extends IMapper<Category> { public List<Category> selectCategoryByType(@Param("type") String type); public void deleteByIds(String ids); public List<Category> selectCategoryByPage(Map<String, Object> map); }
5、CategoryMapping.xml不需要什么改动
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.jdw.dao.CategoryMapper"> <resultMap id="BaseResultMap" type="com.jdw.bean.Category"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> <id column="c_id" property="cId" jdbcType="INTEGER" /> <result column="c_name" property="cName" jdbcType="VARCHAR" /> <result column="hot" property="hot" jdbcType="BIT" /> </resultMap> <sql id="Base_Column_List"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> c_id, c_name, hot </sql> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> select <include refid="Base_Column_List" /> from category where c_id = #{cId,jdbcType=INTEGER} </select> <select id="selectCategoryByType" resultMap="BaseResultMap" parameterType="java.lang.String"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> select <include refid="Base_Column_List" /> from category where 1 = 1 <if test="type != null and type !=''"> AND c_name = #{type,jdbcType=VARCHAR} </if> ORDER BY c_id </select> <select id="selectCategoryByPage" resultMap="BaseResultMap" parameterType="java.util.Map"> select <include refid="Base_Column_List" /> from category where 1 = 1 <if test="type != null and type !=''"> AND c_name = #{type,jdbcType=VARCHAR} </if> ORDER BY c_id limit #{pageIndex},#{pageSize} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> delete from category where c_id = #{cId,jdbcType=INTEGER} </delete> <insert id="insert" parameterType="com.jdw.bean.Category"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> insert into category (c_id, c_name, hot) values (#{cId,jdbcType=INTEGER}, #{cName,jdbcType=VARCHAR}, #{hot,jdbcType=BIT}) </insert> <insert id="insertSelective" parameterType="com.jdw.bean.Category"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> insert into category <trim prefix="(" suffix=")" suffixOverrides=","> <if test="cId != null"> c_id, </if> <if test="cName != null"> c_name, </if> <if test="hot != null"> hot, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="cId != null"> #{cId,jdbcType=INTEGER}, </if> <if test="cName != null"> #{cName,jdbcType=VARCHAR}, </if> <if test="hot != null"> #{hot,jdbcType=BIT}, </if> </trim> </insert> <update id="updateByPrimaryKeySelective" parameterType="com.jdw.bean.Category"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> update category <set> <if test="cName != null"> c_name = #{cName,jdbcType=VARCHAR}, </if> <if test="hot != null"> hot = #{hot,jdbcType=BIT}, </if> </set> where c_id = #{cId,jdbcType=INTEGER} </update> <update id="updateByPrimaryKey" parameterType="com.jdw.bean.Category"> <!-- WARNING - @mbggenerated This element is automatically generated by MyBatis Generator, do not modify. --> update category set c_name = #{cName,jdbcType=VARCHAR}, hot = #{hot,jdbcType=BIT} where c_id = #{cId,jdbcType=INTEGER} </update> </mapper>
6、来点猛料,实现IMapper接口的BaseDaoImpl,注意看其中的T,spring可以Autowired泛型T,这个很巧妙!
package com.jdw.dao.impl; import org.springframework.beans.factory.annotation.Autowired; import com.jdw.bean.IModel; import com.jdw.dao.IMapper; /** * 面向接口+泛型的威力初体验 * * @author Administrator * * @param <T> * @param <M> */ public class BaseDaoImpl<T extends IMapper<M>,M extends IModel> implements IMapper<M> { @Autowired protected T t; @Override public int deleteByPrimaryKey(Integer id) { int result = this.t.deleteByPrimaryKey(id); return result; } @Override public int insert(M model) { int result = this.t.insert(model); return result; } @Override public int insertSelective(M model) { int result = this.t.insertSelective(model); return result; } @Override public M selectByPrimaryKey(Integer id) { M m=this.t.selectByPrimaryKey(id); return m; } @Override public int updateByPrimaryKeySelective(M model) { int result=this.t.updateByPrimaryKeySelective(model); return result; } @Override public int updateByPrimaryKey(M model) { int result=this.t.updateByPrimaryKey(model); return result; } }
7、继承了BaseDaoImpl的CategoryDaoImpl,注意少了很多共性代码,只有特性接口的实现,连spring mapper注入都省了!
package com.jdw.dao.impl; import java.util.List; import java.util.Map; import org.springframework.stereotype.Repository; import com.jdw.bean.Category; import com.jdw.dao.CategoryMapper; /** * 继承了BaseDaoImpl的CategoryImpl * 注意: * (1)这里只需要实现特有的接口方法 * (2)注意这里的mybatis mapper是根据泛型从BaseDaoImpl继承而来的 * @author Administrator * */ @Repository(value = "categoryDao") public class CategoryDaoImpl extends BaseDaoImpl<CategoryMapper, Category> implements CategoryMapper { @Override public List<Category> selectCategoryByType(String type) { List<Category> list = this.t.selectCategoryByType(type); return list; } @Override public void deleteByIds(String ids) { } @Override public List<Category> selectCategoryByPage(Map<String, Object> map) { List<Category> list = this.t.selectCategoryByPage(map); return list; } }
8、BaseService接口
package com.jdw.service; import com.jdw.bean.IModel; import com.jdw.dao.IMapper; import com.jdw.dao.impl.BaseDaoImpl; /** * 共性的泛型化的Service接口 * @author Administrator * * @param <M> * @param <T> * @param <D> */ public interface BaseService<M extends IModel,T extends IMapper<M>, D extends BaseDaoImpl<T,M>> { int insert(M model); int insertSelective(M model); int updateByPrimaryKeySelective(M model); int updateByPrimaryKey(M model); int deleteByPrimaryKey(int id); M selectByPrimaryKey(int id); }
9、继承了BaseService接口的CategoryService接口
package com.jdw.service; import java.util.List; import java.util.Map; import com.jdw.bean.Category; import com.jdw.dao.CategoryMapper; import com.jdw.dao.impl.CategoryDaoImpl; /** * 继承了BaseService接口的CategoryService接口 * @author Administrator * */ public interface CategoryService extends BaseService<Category,CategoryMapper,CategoryDaoImpl> { public Map<String,Object> query(String type, Integer page, Integer size); public void deleteByIds(String ids); public List<Category> getAll(Map<String,Object> map); }
10、BaseServiceImpl
package com.jdw.service.impl; import org.springframework.beans.factory.annotation.Autowired; import com.jdw.bean.IModel; import com.jdw.dao.IMapper; import com.jdw.dao.impl.BaseDaoImpl; import com.jdw.service.BaseService; /** * 泛型化的共性service实现 * @author Administrator * * @param <M> * @param <T> * @param <D> */ public class BaseServiceImpl<M extends IModel,T extends IMapper<M>, D extends BaseDaoImpl<T,M>> implements BaseService<M, T, D> { @Autowired protected D dao; @Override public int insert(M model) { int result=dao.insert(model); return result; } @Override public int insertSelective(M model) { int result=dao.insertSelective(model); return result; } @Override public int updateByPrimaryKeySelective(M model) { int result=dao.updateByPrimaryKeySelective(model); return result; } @Override public int updateByPrimaryKey(M model) { int result=dao.updateByPrimaryKey(model); return result; } @Override public int deleteByPrimaryKey(int id) { int result=dao.deleteByPrimaryKey(id); return result; } @Override public M selectByPrimaryKey(int id) { M model=dao.selectByPrimaryKey(id); return model; } }
11、CategoryServiceImpl,原理同7,不再赘述
package com.jdw.service.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.jdw.bean.Category; import com.jdw.dao.CategoryMapper; import com.jdw.dao.impl.CategoryDaoImpl; import com.jdw.service.CategoryService; @Service("categoryService") public class CategoryServicImpl extends BaseServiceImpl<Category, CategoryMapper, CategoryDaoImpl> implements CategoryService { @Override public void deleteByIds(String ids) { } @Override public Map<String, Object> query(String type, Integer pageNo, Integer pageSize) { pageNo = pageNo == null ? 1 : pageNo; pageSize = pageSize == null ? 10 : pageSize; PageHelper.startPage(pageNo, pageSize); List<Category> list = this.dao.selectCategoryByType(type); for (Category c : list) { System.out.println(c); } // 用PageInfo对结果进行包装 PageInfo<Category> page = new PageInfo<Category>(list); // 测试PageInfo全部属性 /* * System.out.println(page.getPageNum()); * System.out.println(page.getPageSize()); * System.out.println(page.getStartRow()); * System.out.println(page.getEndRow()); * System.out.println(page.getTotal()); * System.out.println(page.getPages()); * System.out.println(page.getFirstPage()); * System.out.println(page.getLastPage()); * System.out.println(page.isHasPreviousPage()); * System.out.println(page.isHasNextPage()); */ Map<String, Object> map = new HashMap<String, Object>(); map.put("total", page.getTotal()); map.put("rows", page.getList()); return map; } @Override public List<Category> getAll(Map<String, Object> map) { return this.dao.selectCategoryByPage(map); } }
12、总结说明
有的人觉的这么写好麻烦啊,又是接口,又是泛型,还是基类的。他们觉得直接Service里面用mapper就行了,又简单又方便,想用哪个mapper就注入哪个mapper。想法有多好,耦合就有多高!
面向接口会让各模块之间的耦合程度很低,比如哪天你不想用mybatis了,只需要修改dao层的实现就可以了,service层不需要动!如果你service里有mybatis注入代码呢?如果service没有接口的话,controller估计也要改了,跟重做没有什么区别,也许更麻烦,面向接口让代码更规范,重用度更高。一句话,面向接口是各种设计模式的基础。
泛型让代码更简练,让共性成为共性,让特性更加特性,一目了然!