mybatis的确很方便,可以随意配置sql语句,并根据参数生成指定的sql,也可以根据查询结果生成指定对象

但是有一点非常恐怖,就是每个数据库表都必须有一个配置,等于在一个系统里做了很多重复的工作,

因为几乎每个表都用到getById,update等操作,今天我们就尝试着把这些操作提取出来,一次性完成.

而不要重复重复再重复. 设想一下一个大型项目,几百张表,要生成几百个mapper.xml  而且这些xml内容差不多.

先来看看准备工作

定义entity的基类,

import java.util.Date;

public class BaseEntity<ID> {
private ID id;
private ID creatorId;
private ID updaterId;
private Date createDate;
private Date updateDate;
private Long updateCount;
private Integer isDelete; public ID getId() {
return id;
} public void setId(ID id) {
this.id = id;
} public Date getUpdateDate() {
return updateDate;
} public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
} public Date getCreateDate() {
return createDate;
} public void setCreateDate(Date createDate) {
this.createDate = createDate;
} public ID getCreatorId() {
return creatorId;
} public void setCreatorId(ID creatorId) {
this.creatorId = creatorId;
} public ID getUpdaterId() {
return updaterId;
} public void setUpdaterId(ID updaterId) {
this.updaterId = updaterId;
} public Long getUpdateCount() {
return updateCount;
} public void setUpdateCount(Long updateCount) {
this.updateCount = updateCount;
} public Integer getIsDelete() {
return isDelete;
} public void setIsDelete(Integer isDelete) {
this.isDelete = isDelete;
}
}

id字段很重要,其余看公司规定.

这里Id使用的是泛型,也就是说它可以使 int,long,甚至String

真正的entity对象定义起来就很容易啦

public class SysUser extends BaseEntity<Integer> {
private Integer userAge;
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
}

然后是定义mapper接口

public interface BaseMapper<T extends BaseEntity<ID>,ID> {
T getById(ID id);
int insert(T entity);
int update(T entity); int deleteByIds(@Param("ids")ID... ids);
int deleteBy(Criteria criteria); int removeByIds(@Param("ids")ID... ids);
int removeBy(Criteria criteria); List<T> getBy(Criteria criteria); int countAll();
int countBy(Criteria criteria); int insertAll(List<T> list);
int updateBy(@Param("criteria")Criteria criteria,@Param("params")T entity); List<T> findAll();
}

这里基本包含我们常用的查询,其余需要级联查询,多表关联的继承这个接口,然后定义这个不常用查询的mapper.xml

public interface SysUserMapper extends BaseMapper<SysUser,Integer>{
int maxId();
}

这个只是Demo自然没什么复杂的东西可以定义

了解过mybatis的人应该知道,mapper接口是需要注册才能使用的,

要写使用这些公用的方法还需要一些步骤.

我们可以使用代码生成器,生成如下类:

public class MapperContainer {
public static interface SysUserMapper extends BaseMapper<SysUser,Integer>{ } public static interface UserlogMapper extends BaseMapper<Userlog,Integer>{ }
}

再有复杂定义时可以继承MapperContainer.XXX,  MapperContainer 有两个作用,第一个作用是防止某些表根本没有复杂定义,使用基本查询即可. 这样不用手写一个接口

第二就是为了方便注册

我们先来看看使用的Demo

public class Demo {

    public static void main(String[] args) throws IOException {
Reader reader = Resources.getResourceAsReader("mybaits-config.xml");
Configuration config = new XMLConfigBuilder(reader, null, null).parse();
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config); OrmProvider.getMapperRegister().registerContainer(MapperContainer.class, config); SqlSession session = factory.openSession(false); MapperContainer.UserlogMapper mapper = session.getMapper(MapperContainer.UserlogMapper.class); List<Userlog> list = new ArrayList<Userlog>();
for(int i=0;i<10;i++){
list.add(new Userlog());
list.get(i).setContext("这是测试内容"+i);
list.get(i).setIpAddress("192.168.56." + i);
}
mapper.insertAll(list); session.commit();
session.close();
} }
OrmProvider.getMapperRegister().registerContainer(MapperContainer.class, config);就是在对这些mapper做注册操作
我们先来看看这个注册接口
public interface MapperRegister {
InputStream createMapper(Class<?> cls);
void register(Class<?> cls,Configuration config);
void registerContainer(Class<?> container,Configuration config);
}

从这个接口上就能看出方便性来,因为如果不是使用容器类,就必须对这些接口一个个注册.

当然这只是一个接口,因为不同数据库的sql也不尽相同,所以需要有不同的调用方式

注册过程如下

public class MysqlMapperRegister extends AbstractMapperRegister {

    public final static String XML_HEADER = "<?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\">";

    private static HashSet<Integer> set = new HashSet<Integer>();

    @SuppressWarnings("rawtypes")
public InputStream createMapper(Class<?> cls) {
if(!BaseMapper.class.isAssignableFrom(cls)){
throw new RuntimeException(cls.getName() + "不是BaseMapper的子类,无法完成注册");
} Class entityCls = (Class) ((ParameterizedType) cls.getGenericInterfaces()[0]).getActualTypeArguments()[0];
Class idCls = (Class) ((ParameterizedType) cls.getGenericInterfaces()[0]).getActualTypeArguments()[1]; StringBuilder builder = new StringBuilder(XML_HEADER);
builder.append("<mapper namespace='");
builder.append(cls.getName());
builder.append("'>"); builder.append("<resultMap type='"+entityCls.getName()+"' id='"+entityCls.getName().replaceAll("[.]", "")+"_resultMap'>");
for(Field field:getAllFields(entityCls)){
builder.append("<id property='"+field.getName()+"' column='"+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+"' />");
}
builder.append("</resultMap>"); builder.append("<select id='getById' parameterType='"+idCls.getName()+"' resultType='");
builder.append(entityCls.getName());
builder.append("'>select * from ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append(" where id = #{id} and ");
builder.append(OrmProvider.getCurrentODeleteStrategy().getUnDeleteCnd());
builder.append("</select>"); builder.append("<insert id='insert' parameterType='");
builder.append(entityCls.getName());
builder.append("' useGeneratedKeys='true' keyProperty='id' >insert into ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls)); builder.append(" <trim prefix='(' suffix=')' suffixOverrides=',' >");
for(Field field:getAllFields(entityCls)){
builder.append("<if test='"+field.getName()+" != null' >"+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+",</if>");
}
builder.append("</trim>"); builder.append("<trim prefix='values (' suffix=')' suffixOverrides=',' >");
for(Field field:getAllFields(entityCls)){
builder.append("<if test='"+field.getName()+" != null' >#{"+field.getName()+"},</if>");
}
builder.append("</trim>"); builder.append("</insert>"); builder.append("<update id='deleteByIds' parameterType='java.util.List'>");
builder.append(OrmProvider.getCurrentODeleteStrategy().createDeleteSql(entityCls));
builder.append(" where id in ");
builder.append("<foreach item='item' index='index' collection='ids' open='(' separator=',' close=')'>#{item}</foreach>");
builder.append(" </update>"); builder.append("<update id='deleteBy' parameterType='com.qdyq.common.criteria.Criteria'>");
builder.append(OrmProvider.getCurrentODeleteStrategy().createDeleteSql(entityCls));
builder.append("<if test='_parameter != null' ><where ><include refid='Global.Where_Clause' /></where></if>");
builder.append(" </update>"); builder.append("<update id='update' parameterType='");
builder.append(entityCls.getName());
builder.append("'>update ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append(" <set>");
for(Field field:getAllFields(entityCls)){
builder.append("<if test='"+field.getName()+" != null' >"+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+" = #{"+field.getName()+"},</if>");
}
builder.append("</set> ,update_count=update_count+1 where id = #{id} and ");
builder.append(OrmProvider.getCurrentODeleteStrategy().getUnDeleteCnd());
builder.append("</update>"); builder.append("<delete id='removeByIds' parameterType='java.util.List'>");
builder.append("delete from ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append(" where id in ");
builder.append("<foreach item='item' index='index' collection='ids' open='(' separator=',' close=')'>#{item}</foreach>");
builder.append(" </delete>"); builder.append("<delete id='removeBy' parameterType='com.qdyq.common.criteria.Criteria'>");
builder.append("delete from ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append(" <if test='_parameter != null' ><where ><include refid='Global.Where_Clause' /></where></if>");
builder.append(" </delete>"); builder.append("<select id='findAll' resultMap='");
builder.append(entityCls.getName().replaceAll("[.]", "")+"_resultMap");
builder.append("'>select * from ");
builder.append(entityCls.getSimpleName());
builder.append(" where ");
builder.append(OrmProvider.getCurrentODeleteStrategy().getUnDeleteCnd());
builder.append("</select>"); builder.append("<insert id='insertAll' parameterType='java.util.List'");
builder.append(" useGeneratedKeys='true' keyProperty='id' >insert into ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls)); builder.append(" (");
boolean notFirst = false;
StringBuilder valuesBuilder = new StringBuilder("(");
for(Field field:getAllFields(entityCls)){
if("id".equals(field.getName()))continue;
if(notFirst){
builder.append(',');
valuesBuilder.append(',');
}else
notFirst = true; valuesBuilder.append("#{item." + field.getName() +"}");
builder.append(OrmProvider.getCurrentOrmStrategy().filed2Column(field));
}
builder.append(") values ");
valuesBuilder.append(")");
builder.append("<foreach collection='list' item='item' index='index' separator=',' > ");
builder.append(valuesBuilder.toString());
builder.append("</foreach>");
builder.append("</insert>"); builder.append("<select id='getBy' parameterType='com.qdyq.common.criteria.Criteria' resultMap='"+entityCls.getName().replaceAll("[.]", "")+"_resultMap' >");
builder.append("select * from ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append("<if test='_parameter != null' ><where ><include refid='Global.Where_Clause' /></where></if>");
builder.append("<if test='hasOrderBy' >order by<foreach collection='orderBys' item='orderBy' separator=',' >${orderBy}</foreach></if>");
builder.append("</select>"); builder.append("<select id='countBy' parameterType='com.qdyq.common.criteria.Criteria' resultType='int'>");
builder.append("select count(*) from ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append("<if test='_parameter != null' ><where ><include refid='Global.Where_Clause' /></where></if>");
builder.append("</select>"); builder.append("<select id='countAll' resultType='int'>");
builder.append("select count(*) from ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append(" where ");
builder.append(OrmProvider.getCurrentODeleteStrategy().getUnDeleteCnd());
builder.append("</select>"); builder.append("<update id='updateBy' parameterType='com.qdyq.common.criteria.Criteria'>");
builder.append("update ");
builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
builder.append(" <set>");
for(Field field:getAllFields(entityCls)){
if("id".equals(field.getName()))continue;
builder.append("<if test='params."+field.getName()+" != null' >"+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+" = #{params."+field.getName()+"},</if>");
}
builder.append("</set> ,update_count=update_count+1 ");
builder.append("<if test='criteria != null' ><where><include refid='Global.Where_Clause2'/></where></if>");
builder.append("</update>"); builder.append("</mapper>"); System.out.println(builder.toString()); return new ByteArrayInputStream(builder.toString().getBytes());
} public void register(Class<?> cls, Configuration config) { if(!set.contains(config.hashCode())){
synchronized(this){
if(!set.contains(config.hashCode()))
try {
set.add(config.hashCode());
new XMLMapperBuilder(Resources.getResourceAsStream("GlobalMapper.xml"),config,"xmlCoder_Global",config.getSqlFragments()).parse();
} catch (IOException e) {
e.printStackTrace();
}
}
} new XMLMapperBuilder(createMapper(cls),config,"xmlCoder_" + cls.getName().replaceAll("[.]", ""),config.getSqlFragments()).parse();
} private List<Field> getAllFields(Class<?> cls){
if(!BaseEntity.class.isAssignableFrom(cls)){
throw new RuntimeException("entity的基類必須是BaseEntity");
}
Field[] fs = cls.getDeclaredFields();
List<Field> result = new ArrayList<Field>();
for(Field f:fs){
if(f.getAnnotation(MapForbidden.class)==null){
result.add(f);
}
}
if(!cls.equals(BaseEntity.class))result.addAll(getAllFields(cls.getSuperclass()));
return result;
} }

过程并不复杂

mybatis泛型(一)的更多相关文章

  1. JPA实现泛型baseServcie+Mybatis

    在开发的过程中,我们总无法避免不同的实体类会去实现相同的操作(增删查改,分页查询等),因此在开发时,我们期望泛型将通用的方法进行包装,使我们能够专注于实体类自身的独特方法,而非一般性常用且重复性高的方 ...

  2. Mybatis框架基础支持层——反射工具箱之泛型解析工具TypeParameterResolver(4)

    简介:TypeParameterResolver是一个工具类,提供一系列的静态方法,去解析类中的字段.方法返回值.方法参数的类型. 在正式介绍TypeParameterResolver之前,先介绍一个 ...

  3. MyBatis的一系列问题的处理(遍历Map集合和智能标签和属性和字段不一样的解决办法 和sql片段)(三)

    一.字段名与属性名(数据库的名字)不一样怎么办? 方案一:在小配置中配置一个resultMapper <!--方案一:resultMapper 字段名与属性名不一致 --> <res ...

  4. mybatis入门基础(二)----原始dao的开发和mapper代理开发

    承接上一篇 mybatis入门基础(一) 看过上一篇的朋友,肯定可以看出,里面的MybatisService中存在大量的重复代码,看起来不是很清楚,但第一次那样写,是为了解mybatis的执行步骤,先 ...

  5. IBatis 2.x 和 MyBatis 3.0.x 的区别(从 iBatis 到 MyBatis)

    从 iBatis 到 MyBatis,你准备好了吗? 对于从事 Java EE 的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate.JPA 这样的一站式对象 / 关系 ...

  6. Mybatis框架基于映射文件和配置文件的方式,实现增删改查,可以打印日志信息

    首先在lib下导入: 与打印日志信息有关的架包 log4j-1.2.16.jar mybatis架包:mybatis-3.1.1.jar 连接数据库的架包:mysql-connector-java-5 ...

  7. Mybatis配置文件

    XML 映射配置文件 MyBatis 的配置文件包含了设置(settings)和属性(properties)信息. properties 这些属性都是可外部配置且可动态替换的,既可以在典型的 Java ...

  8. Cause: org.apache.ibatis.reflection.ReflectionException: Could not set property 'orderdetails' of 'class com.luchao.mybatis.first.po.Orders' with value 'Orderdetail [id=null, ordersId=3, itemsId=1, it

    从上面异常的解释来看是因为反射不能将Orders设置到orderdetails属性上,仔细检查了MyBatis的配置文件,发现: <collection property="order ...

  9. MyBatis学习--mybatis开发dao的方法

    简介 使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法. 主要概念介绍: MyBatis中进行Dao开发时候有几个重要的类,它们是SqlSessionFac ...

随机推荐

  1. 周强201771010141《面向对象程序设计(java)》第一周学习总结

    周强201771010141<面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com ...

  2. cmake使用方法详解

    cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性 ...

  3. 通过父元素的hover控制子元素的显示

    .searbar_content_box:hover .searchBar_checked_detail_box{ display:block}

  4. 我的代码-cleaning

    # coding: utf-8 # In[18]: import pandas as pdimport numpy as npfrom sklearn import treefrom sklearn. ...

  5. 启动Kernel提示Bad Data CRC

    如上图,我明明将uImage正确写入到里nandflash里面,但启动但时候就是提示bad CRC. 后来我手动执行nand read kernel想看看是不是环境变量里面的命令执行有问题,意外但被我 ...

  6. 无旋treap

    #ifndef FHQTREAP_H_INCLUDED #define FHQTREAP_H_INCLUDED //author Eterna #define Hello The_Cruel_Worl ...

  7. java设计模式--UML类图

    2016-06-07 22:46:16 下面简单介绍UML类图:(图是截取的,大家可以用UML工具去画) 1.描述类的类图 类:Person 属性:name   age   sex 访问权限:-  表 ...

  8. Dynamics 365 CRM large instance copy

    使用CRM 大家想必都做过copy. 从一个instance 复制到另外一个instance. 如果你是Dynamics 365 CRM 用户, 并且你的instance超过500GB,甚至1TB+的 ...

  9. Redis中存入存储的编码方式不一致解决问题

    在利用redis缓存的时候,存入的数据与取出的数据编码方式不一致解决办法. from redis import StrictRedis #ecoding = 'utf-8',默认解码方式为bytes, ...

  10. php最常见最经典的算法题

    1.一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫 ...