mybatis泛型(一)

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

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

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

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

先来看看准备工作

定义entity的基类,

import java.util.Date;

public class BaseEntity {
    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;
    }
}
View Code

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

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

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

public class SysUser extends BaseEntity {
    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;
    }
}
View Code

然后是定义mapper接口

public interface BaseMapperextends BaseEntity,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 getBy(Criteria criteria);
    
    int countAll();
    int countBy(Criteria criteria);
    
    int insertAll(List list);
    int updateBy(@Param("criteria")Criteria criteria,@Param("params")T entity);
    
    List findAll();
}
View Code

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

public interface SysUserMapper extends BaseMapper{
        int maxId();
    }

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

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

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

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

public class MapperContainer {
    public static interface SysUserMapper extends BaseMapper{
        
    }
    
    public static interface UserlogMapper extends BaseMapper{
        
    }
}

再有复杂定义时可以继承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 list = new ArrayList();
        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 = "";
    
    private static HashSet set = new HashSet();
    
    @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("");
        
        builder.append("");
        for(Field field:getAllFields(entityCls)){
            builder.append("");
        }
        builder.append("");
        
        builder.append("");
        
        builder.append("insert into ");
        builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
        
        builder.append(" ");
        for(Field field:getAllFields(entityCls)){
            builder.append(""+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+",");
        }
        builder.append("");
        
        builder.append("");
        for(Field field:getAllFields(entityCls)){
            builder.append("#{"+field.getName()+"},");
        }
        builder.append("");
        
        builder.append("");
        
        builder.append("");
        builder.append(OrmProvider.getCurrentODeleteStrategy().createDeleteSql(entityCls));
        builder.append(" where id in ");
        builder.append("#{item}");
        builder.append(" ");
        
        builder.append("");
        builder.append(OrmProvider.getCurrentODeleteStrategy().createDeleteSql(entityCls));
        builder.append("");
        builder.append(" ");
        
        builder.append("update ");
        builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
        builder.append(" ");
        for(Field field:getAllFields(entityCls)){
            builder.append(""+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+" = #{"+field.getName()+"},");
        }
        builder.append(" ,update_count=update_count+1  where id = #{id} and ");
        builder.append(OrmProvider.getCurrentODeleteStrategy().getUnDeleteCnd());
        builder.append("");
        
        builder.append("");
        builder.append("delete from ");
        builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
        builder.append(" where id in ");
        builder.append("#{item}");
        builder.append(" ");
        
        builder.append("");
        builder.append("delete from ");
        builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
        builder.append(" ");
        builder.append(" ");
        
        builder.append("");
        
        builder.append(");
        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(" ");
        builder.append(valuesBuilder.toString());
        builder.append("");
        builder.append("");

        builder.append("");
        
        builder.append("");
        
        builder.append("");
        
        builder.append("");
        builder.append("update ");
        builder.append(OrmProvider.getCurrentOrmStrategy().class2Table(entityCls));
        builder.append(" ");
        for(Field field:getAllFields(entityCls)){
            if("id".equals(field.getName()))continue;
            builder.append(""+OrmProvider.getCurrentOrmStrategy().filed2Column(field)+" = #{params."+field.getName()+"},");
        }
        builder.append(" ,update_count=update_count+1 ");
        builder.append("");
        builder.append("");
        
        builder.append("");
        
        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 getAllFields(Class cls){
        if(!BaseEntity.class.isAssignableFrom(cls)){
            throw new RuntimeException("entity的基類必須是BaseEntity");
        }
        Field[] fs = cls.getDeclaredFields();
        List result = new ArrayList();
        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;
    }
    
}
View Code

过程并不复杂

转载于:https://www.cnblogs.com/yangyang12138/p/7563270.html

你可能感兴趣的:(mybatis泛型(一))