Mybatis 进行简单通用的封装
2016-11-30 21:57
399 查看
配置文件
当Spring和Mybatis集成时,可以利用通配符的形式注册Mapper配置文件<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath*:mybatis-mapper/**/*.xml"/> </bean>
Mapper
mapper的生成除了网上普遍的generator的jar包之外,自己还可以实现一个简单的模板生成:我用的是Freemarker进行模板渲染,自动生成常用的sql:
package org.digdata.swustoj.client; import freemarker.template.TemplateException; import org.apache.commons.io.FileUtils; import org.digdata.swustoj.annotation.Mapping; import org.digdata.swustoj.util.BeanUtil; import org.digdata.swustoj.util.FreeMarkerUtil; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.junit.Test; import java.io.File; import java.io.IOException; import java.util.*; /** * Created by hongfei.whf on 2016/11/26. */ public class MapperGenerator { private String output_dir = "E:\\tmp\\output"; private String class_path = Thread.currentThread().getContextClassLoader().getResource("").getPath(); private final static SAXReader reader = new SAXReader(); private List<Class<?>> classes = BeanUtil.scan("org.digdata.swustoj.entity"); private String path1 = "auto"; private String path2 = "impl"; @Test public void run() throws ClassNotFoundException, IOException, IllegalAccessException, InstantiationException, TemplateException, DocumentException { for (Class clazz : classes) { if (clazz.getSimpleName().endsWith("WithBLOBs")) continue; Mapping mapping = (Mapping) clazz.getAnnotation(Mapping.class); String className = clazz.getCanonicalName(); String namespace = className.replace("entity", "dao") + "Mapper"; String tableName = mapping.tableName(); String resultMap = getResultMap(clazz); String queryType = mapping.queryType().getCanonicalName(); Map<String, Object> map = new HashMap<>(); map.put("namespace", namespace); map.put("queryType", queryType); map.put("tableName", tableName); map.put("resultMap", resultMap); ArrayList fields = new ArrayList(); Class extendsClass = clazz; fields.addAll(Arrays.asList(clazz.getDeclaredFields())); try { extendsClass = Class.forName(clazz.getCanonicalName() + "WithBLOBs"); fields.addAll(Arrays.asList(extendsClass.getDeclaredFields())); } catch (Exception e) { // } map.put("ownType", extendsClass.getCanonicalName()); map.put("fields", fields); String template_path = class_path + File.separator + "mybatis-mapper/template/TemplateMapper.ftl"; String template = FileUtils.readFileToString(new File(template_path)); String custom_path = class_path + File.separator + "mybatis-mapper/template/CustomMapper.ftl"; String custom = FileUtils.readFileToString(new File(custom_path)); String TemplateContent = FreeMarkerUtil.proccessTemplate(clazz.getCanonicalName(), template, map); String auto_render_template_file_path = getRenderPath(clazz, true); FileUtils.write(new File(auto_render_template_file_path), TemplateContent); String CustomContent = FreeMarkerUtil.proccessTemplate(clazz.getCanonicalName(), custom, map); String auto_render_custom_file_path = getRenderPath(clazz, false); FileUtils.write(new File(auto_render_custom_file_path), CustomContent); } } private String getResultMap(Class clazz) throws DocumentException { String mapperFilePath = class_path + File.separator + "mybatis-mapper" + File.separator + clazz.getSimpleName() + "Mapper.xml"; Document document = reader.read(new File(mapperFilePath)); Element root = document.getRootElement(); if ("mapper".equals(root.getName())) { Iterator iter = root.elementIterator(); while (iter.hasNext()) { Element currElement = (Element) iter.next(); if ("resultMap".equals(currElement.getName())) { if ("ResultMapWithBLOBs".equals(currElement.attributeValue("id"))) { return "ResultMapWithBLOBs"; } } } } return "BaseResultMap"; } private String getRenderPath(Class clazz, Boolean isTemplate) { return output_dir + File.separator + (isTemplate ? path1 : path2) + File.separator + clazz.getSimpleName() + "Mapper.xml"; } }
模板1:
<?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="${namespace}"> <!-- query ${tableName} --> <select id="query" resultMap="${resultMap}" parameterType="${queryType}"> select * from ${tableName} <include refid="condition"/> <include refid="orderby"/> <if test="start != null and rows != null"> <#noparse>limit #{start},#{rows}</#noparse> </if> </select> <!-- count ${tableName} --> <select id="count" resultType="java.lang.Integer" parameterType="${queryType}"> select count(*) from ${tableName} <include refid="condition"/> </select> <!-- query ${tableName} by ids --> <select id="queryByIds" parameterType="java.util.List" resultMap="${resultMap}"> select * from ${tableName} <where> ${tableName}.id in <foreach collection="list" item="item" open="(" separator="," close=")"> <#noparse>#{item}</#noparse> </foreach> </where> </select> <!-- delete ${tableName} by ids --> <delete id="delete" parameterType="${queryType}"> delete from ${tableName} <include refid="condition"/> </delete> <!-- save batch ${tableName} --> <insert id="saveBatch" parameterType="java.util.List"> insert into ${tableName} <trim prefix="(" suffix=")" suffixOverrides=","> <#list fields as field> ${field.name}, </#list> </trim> value <foreach item="item" index="index" collection="list" separator=","> <trim prefix="(" suffix=")" suffixOverrides=","> <#list fields as field> <#noparse>#{item.</#noparse>${field.name}<#noparse>},</#noparse> </#list> </trim> </foreach> </insert> <!-- save ${tableName} And Return Id --> <insert id="saveAndRetId" parameterType="${ownType}" useGeneratedKeys="true" keyProperty="id"> insert into ${tableName} <trim prefix="(" suffix=")" suffixOverrides=","> <#list fields as field> <if test="${field.name} != null"> ${field.name}, </if> </#list> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <#list fields as field> <if test="${field.name} != null"> <#noparse>#{</#noparse>${field.name}<#noparse>},</#noparse> </if> </#list> </trim> </insert> </mapper>
模板2:
<?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="${namespace}"> <!-- 若要进行修改,请在此补全sql,防止以后模板扩展带来的代码迁移的不便 --> <!-- 注意,此两处sql均被使用到,请勿注释或删除 --> <!-- where sql --> <sql id="condition"> <where> 1=1 </where> </sql> <!-- orderby sql --> <sql id="orderby"> </sql> </mapper>
Dao层统一封装
我利用的是Spring4.0提供的泛型注入:package org.digdata.swustoj.dao; import org.digdata.swustoj.annotation.CacheAccess; import org.digdata.swustoj.annotation.CacheFlush; import org.digdata.swustoj.query.PageQuery; import java.util.List; /** * Created by hongfei.whf on 2016/8/27. */ public interface BaseDao<T, Q extends PageQuery> { /** * 删除指定id * * @param id * @return */ @CacheFlush int deleteByPrimaryKey(Integer id); /** * 插入 * * @param record * @return */ @CacheFlush int insert(T record); /** * 条件插入 * * @param record * @return */ @CacheFlush int insertSelective(T record); /** * 查询指定id * * @param id * @return */ @CacheAccess(type = Object.class) T selectByPrimaryKey(Integer id); /** * 根据id条件更新 * * @param record * @return */ @CacheFlush int updateByPrimaryKeySelective(T record); /** * 根据id更新 * * @param record * @return */ @CacheFlush int updateByPrimaryKey(T record); /** * 条件查询 * * @param query * @return */ @CacheAccess(type = List.class) List<T> query(Q query); /** * 根据ids查询 * * @param ids * @return */ @CacheAccess(type = List.class) List<T> queryByIds(List<Integer> ids); /** * 条件查询数量 * * @param query * @return */ @CacheAccess(type = Integer.class) Integer count(Q query); /** * 删除 * * @param query * @return */ @CacheFlush Boolean delete(Q query); /** * 添加 * * @param record * @return */ @CacheFlush Boolean save(T record); /** * 更新 * * @param record * @return */ @CacheFlush Boolean update(T record); /** * 批量插入 * * @param list * @return */ @CacheFlush Boolean saveBatch(List<T> list); /** * 插入并返回主键 * * @param t * @return */ @CacheFlush Integer saveAndRetId(T t) throws NoSuchFieldException, IllegalAccessException; }
注意:这里的注解和Mybatis无关,主要实现与Memcache的统一操作
Dao统一封装实现类
package org.digdata.swustoj.dao.impl; import org.digdata.swustoj.dao.BaseDao; import org.digdata.swustoj.query.PageQuery; import org.digdata.swustoj.util.BeanUtil; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.util.List; /** * Created by hongfei.whf on 2016/8/27. */ public abstract class BaseDaoImpl<T, Q extends PageQuery> extends SqlSessionDaoSupport implements BaseDao<T, Q> { /** * 获取mapper的namespace * * @return */ public abstract String getNameSpace(); /** * 获取子类型,推荐填写T的class,,用于缓存序列化和反序列化的实现 * * @return */ public abstract Class getSubType(); @Override public int deleteByPrimaryKey(Integer id) { return this.getSqlSession().delete(getNameSpace() + ".deleteByPrimaryKey", id); } @Override public int insert(T record) { return this.getSqlSession().insert(getNameSpace() + ".insert", record); } @Override public int insertSelective(T record) { return this.getSqlSession().insert(getNameSpace() + ".insertSelective", record); } @Override public T selectByPrimaryKey(Integer id) { return this.getSqlSession().selectOne(getNameSpace() + ".selectByPrimaryKey", id); } @Override public int updateByPrimaryKeySelective(T record) { return this.getSqlSession().update(getNameSpace() + ".updateByPrimaryKeySelective", record); } @Override public int updateByPrimaryKey(T record) { return this.getSqlSession().update(getNameSpace() + ".updateByPrimaryKey", record); } @Override public List<T> query(Q query) { return this.getSqlSession().selectList(getNameSpace() + ".query", query); } @Override public List<T> queryByIds(List<Integer> list) { return this.getSqlSession().selectList(getNameSpace() + ".queryByIds", list); } @Override public Integer count(Q query) { return this.getSqlSession().selectOne(getNameSpace() + ".count", query); } @Override public Boolean delete(Q query) { return this.getSqlSession().delete(getNameSpace() + ".delete", query) > 0 ? true : false; } @Override public Boolean save(T record) { return this.insertSelective(record) > 0 ? true : false; } @Override public Integer saveAndRetId(T t) throws NoSuchFieldException, IllegalAccessException { if (this.getSqlSession().insert(getNameSpace() + ".saveAndRetId", t) > 0) { return BeanUtil.getFieldValue(t, "id", Integer.class); } return null; } @Override public Boolean update(T record) { return this.updateByPrimaryKeySelective(record) > 0 ? true : false; } @Override public Boolean saveBatch(List<T> list) { return this.getSqlSession().insert(getNameSpace() + ".saveBatch", list) > 0 ? true : false; } }
使用方式:
@Repository public class ProblemDaoImpl extends BaseDaoImpl<ProblemWithBLOBs, ProblemQuery> implements ProblemDao { // .... }
Service层的统一封装
Service层的封装参考Dao层的封装即可,我主要封装的是分页,批量操作等。相关文章推荐
- 边做边学小型封装--利用主流框架进行Dao层通用化,Spring3.0+Hibernate3.3.2通用Dao层整合(一)
- 边做边学小型封装--利用主流框架进行Dao层通用化,Spring3.0+Hibernate3.3.2通用Dao层整合(三)
- MyBatis封装简单的CRUD
- Mybatis通用DAO设计封装(mybatis)
- 对下载进行一个简单的封装
- js中用数组对一些验证进行简单的封装
- 简单对七牛.Net API管理文件进行简单封装的类
- 1个比较简单的使用java反射机制获取前台数据进行数据封装的例子
- 简单通用JDBC辅助类封装
- notepad Mybatis通用DAO设计封装
- 边做边学小型封装--利用主流框架进行Dao层通用化,Spring3.0+Hibernate3.3.2通用Dao层整合(四)
- 对Pthread线程进行简单的类封装
- 简单封装VFW类进行视频应用开发
- 用bolck对ASIHttpRequst进行简单的封装
- 使用闭包对setTimeout进行简单封装避免出错
- 边做边学小型封装--利用主流框架进行Dao层通用化,Spring3.0+Hibernate3.3.2通用Dao层整合(二)
- 对libpq进行简单的c++封装
- 【pthread系列-11】对Pthread线程进行简单的类封装
- 对数据库DML操作进行封装成简单的工具
- JavaScript面向对象编程(12)对js进行简单封装