Mybatis 封装通用的增删改查

本贴最后更新于 2953 天前,其中的信息可能已经事过境迁

曾经发过一篇文章,大概写的就是阿海多么多么厉害,见到某位同事在Hibernate的基础上封装了一下,就以一己之力开发什么什么框架,最后写了个超大的一坨的事。
那么,后续篇来了。阿海不是自负之人,当之前的CRUD框架并没有达到理想的结果时,阿海转向了Mybatis封装。别问我为什么不是Hibernate。我本来就不喜欢Hibernate,即使在之前的一家公司一直被强制性的约束使用Hibernate时,也没有对Hibernate产生什么真正的好感,反而屡次发现了Hibernate的一些问题。

或许是因为版本太老了得缘故吧(都是2016年的新世纪了,还在用Hibernate2)总之,bug层出不穷,极不稳定,而且还因为版本过老的远古,一些依赖或者受影响的包也必须使用老版本,哎不管怎么说,在那段逗逼的时光里敲着逗逼的代码,做着逗逼的事情。重复着逗逼的生活。所以,说到封装,我第一时间想到了mybatis。版本嘛,不高不低,就用我最熟练的3.2版本。至于我为什么不用更高的版本,主要是我第一次做系统的封装,先用我最拿手的试试,尽管说是最拿手的,但也好长时间没有玩儿过了,苦逼的玩儿了一年的hibernate2对于阿海的性格来说,简直就是煎熬。

扯了那么多没用的,接下来说说我这个Hibernate呃,打错了,是我这个MyBatis封装和之前的那个Hibernate封装有什么区别和优势。首先,最大的区别就是,Mybatis少不了xml文件。因为这是Mybatis的本质,也是他的精华所在。另外呢,就是没有防注入功能。占位付功能,在我封装后的Mybaits中,彻底废掉了。也不能说是彻底废掉,只是那些公用方法中的占位付给废掉了。当然,解决SQL注入并不一定非得让框架去支持,自己也可以写,随便写个参数拦截器就好了,当然也必须要写,不仅仅是为了解决SQL注入,比如html标记转义、敏感字符过滤直来的都是要有的吧?所以说,废掉通用方法中的占位付功能并不是一个不明智的选择。

接下来就是与Hibernate之间的缓存效率对比,准确的说是与那个封装之后的Hibernate的缓存对比。Hibernate的(缓存+事物)问题相信一些精通的朋友应该知道,当然,即使有一些知道的我还是要简单的说一下,毕竟一些朋友还是不知道的。。

在这段文字中,我觉得我应该严肃一下,不再逗逼。好了,且听我说:所谓缓存机制,Hibernate中的二级缓存利用了一个叫做“快照”的逗逼机制,本体来说的确挺厉害,然而碰到事物,就…就….这就尴尬了-_-!。为什么这么说呢?我先来介绍一下Hibernate的快照原理。当hibernate查询时,会给这个语句的结果生成一个缓存和快照,当再次查询时,他会从缓存中找到要查询的对象,然后与快照中的对比,当缓存和快照中的id(Hibernate给他定义的对象ID,叫OID,对象更新后OID会变)一致时,将不会从数据库中再次查询。而是直接使用缓存中的对象。这样,减少了sql语句的查询。对效率有一定的优化。那么问题来了,当开启事务时,每执行一次操作,缓存都会更新一次,而快照则是在提交之后才会更新。那么问题来了,当执行完一些sql时,缓存更新,这时候如果遭到回滚的话,快照则不会更新。那么这个更新后的缓存就是一个废弃的缓存,就是一个脏数据。如果正好用户没有配置快照的话,再次查询出来的数据则不会和数据库中的数据同步。所以就产生了错误数据。

去其他的就不用说了吧?这套基于Mybatis的封装保留了Mybatis的精髓,你依然可以配置mapper,编写xml,使用动态SQL,充分的发挥软编码的特性。
是上面吹了这么多,接下来应该说一下这个封装的结构了。其实也没有什么结构可言,因为之前写过那个不算完美的CRUD框架,所以很多东西都可以拿来服用,至少SQL生成这一块和注解这一块基本上可以复制粘贴。
通用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.aiyi.core.dao.Dao">
<!-- 局部新增 -->
<insert id="addLocal">
${value}
</insert>

&lt;!-- 整体新增 --&gt;
&lt;insert id="add"&gt;
    ${value}
&lt;/insert&gt;

&lt;!-- 根据ID查询单个 --&gt;
&lt;select id="getById" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 根据ID查询单个字段 --&gt;
&lt;select id="getFieldById" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 根据条件查询单个 --&gt;
&lt;select id="getByParm" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 根据条件查询单个字段 --&gt;
&lt;select id="getFieldByParm" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 条件查询列表 --&gt;
&lt;select id="selectList" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 条件查询字段列表 --&gt;
&lt;select id="selectListField" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 更新局部 --&gt;
&lt;update id="updateLocal"&gt;${value}&lt;/update&gt;

&lt;!-- 更新全部 --&gt;
&lt;update id="update"&gt;${value}&lt;/update&gt;

&lt;!-- 条件更新局部 --&gt;
&lt;update id="updateLocalByPram"&gt;${value}&lt;/update&gt;

&lt;!-- 条件更新全部 --&gt;
&lt;update id="updateByPram"&gt;${value}&lt;/update&gt;


&lt;!-- 根据ID删除 --&gt;
&lt;delete id="deleteById"&gt;
    ${value}
&lt;/delete&gt;

&lt;!-- 批量删除 --&gt;
&lt;delete id="deleteByparm"&gt;
    ${value}
&lt;/delete&gt;

&lt;!-- 自定义语句查询 --&gt;
&lt;select id="selectBySql" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 自定义语句执行 --&gt;
&lt;update id="excuse"&gt;${value}&lt;/update&gt;


&lt;!-- 查询符合条件的数量 --&gt;
&lt;select id="selectCountByParm" resultType="Long"&gt;
    ${value}
&lt;/select&gt;


&lt;!-- 查询总数量 --&gt;
&lt;select id="selectCount" resultType="Long"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 内查询 --&gt;
&lt;select id="selectIn" resultType="hashmap"&gt;
    ${value}
&lt;/select&gt;

&lt;!-- 获取下一个序列的值 --&gt;
&lt;select id="fetchSeqNextval" resultType="Long" flushCache="true"&gt;
    ${value}
&lt;/select&gt;

</mapper>







从这个 mapper 文件中可以看出为什么没有占位符了吧?

接下来就是通用 dao


package com.aiyi.core.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import com.aiyi.core.beans.Po;
import com.aiyi.core.beans.WherePrams;

/**
 * 公共数据库操作层
 * @author 郭胜凯
 * @time 2016年5月3日下午2:55:13
 * @email 719348277@qq.com
 * @param <T> 实体PO类型
 * @param <PK> PO主键类型
 */
public interface Dao<T extends Po, PK extends Serializable> {

    /**
     * 添加不为空的记录(只将不为空字段入库,效率高)
     * @param po
     * @return 受改变的记录数
     */
    public int addLocal(T po);

    /**
     * 记录添加(所有字段入库,效率中)
     * @param po
     * @return
     */
    public int add(T po);

    /**
     * 通过主键获取某个记录
     * @param id 主键
     * @return PO
     */
    public T get(PK id);

    /**
     * 通过主键获取某个字段的值
     * @param id
     * @param fileName
     * @return
     */
    public Serializable getField(PK id, String fileName);

    /**
     * 条件获取一条记录
     * @param t
     * @param 条件表达式
     * @return PO
     */
    public T get(WherePrams where);

    /**
     * 条件获取某个记录字段
     * @param where
     * @param fileName
     * @return
     */
    public Serializable getFile(WherePrams where, String fileName);

    /**
     * 条件查询列表
     * @param where 条件表达式
     * @return PO列表
     */
    public List<T> list(WherePrams where);

    /**
     * 查询某个字段列表
     * @param where 条件表达式
     * @param fileName 要查询的字段
     * @return
     */
    public Serializable[] listFile(WherePrams where, String fileName);

    /**
     * 查询某些字段
     * @param where 条件表达式
     * @param files 要查询的字段集
     * @return 查询的PO字段列表
     */
    public List<Map<String, Serializable>> listFiles(WherePrams where, String[] files);

    /**
     * 更新不为null的PO字段
     * @param po
     * @return 受影响的行数
     */
    public int updateLocal(T po);

    /**
     * 更新PO的所有字段
     * @param po
     * @return 受影响的行数
     */
    public int update(T po);

    /**
     * 条件更新不为null的字段
     * @param po
     * @param 条件表达式
     * @return 受影响的行数
     */
    public int updateLocal(T po, WherePrams where);

    /**
     * 条件更新所有字段
     * @param po
     * @param 条件表达式
     * @return 受影响的行数
     */
    public int update(T po, WherePrams where);

    /**
     * 删除某个记录
     * @param id 主键
     * @return 受影响的行数
     */
    public int del(PK id);

    /**
     * 条件删除某个记录
     * @param where 条件表达式
     * @return 受影响的行数
     */
    public int del(WherePrams where);

    /**
     * 自定义sql查询
     * @param po 用于封装返回结果的Bean
     * @param sql 用于执行查询的Sql
     * @param args Sql占位付对应的参数
     * @return 结果集合
     */
    public List<Map<String, Object>> listBySql(String sql);

    /**
     * 执行自定义sql
     * @param sql 用于执行的Sql
     * @param args Sql占位付对应的参数
     * @return 受影响的行数
     */
    public int excuse(String sql);

    /**
     * 获取指定条件的记录数
     * @param where 条件表达式
     * @return 查询到的记录数
     */
    public long count(WherePrams where);

    /**
     * 获取对应表中的记录数
     * @return 表中的条数
     */
    public long size();

    /**
     * 是否存在字段相同的记录(ID以及不为空的字段除外)
     * @param po 参照实体
     * @return
     */
    public boolean isExist(T po);

    /**
     * 是否存在指定条件的记录
     * @param where 条件表达式
     * @return
     */
    public boolean isExist(WherePrams where);

    /**
     * 内查询
     * @param fileName 用于内查询的字段
     * @param values 字段的值
     * @return 查询到的结果集
     */
    public List<T> in(String fileName, Serializable[] values);

    /**
     * 获得下一个序列的值
     * @return
     */
    public long nextId();
}
	<p>
		<br />
	</p>
	<p style="text-indent:21.25pt;">
		以及DAO的实现类
	</p>
	<p style="text-indent:21.25pt;">
package com.aiyi.core.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.ConnectException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.aiyi.core.annotation.po.FieldName;
import com.aiyi.core.beans.Method;
import com.aiyi.core.beans.Po;
import com.aiyi.core.beans.Pram;
import com.aiyi.core.beans.WherePrams;
import com.aiyi.core.dao.Dao;
import com.aiyi.core.sql.where.C;
import com.aiyi.core.sql.where.SqlUtil;
import com.aiyi.core.util.GenericsUtils;

@SuppressWarnings("unused")
@Repository
public class DaoImpl<T extends Po, PK extends Serializable> implements Dao<T, PK> {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource(name = "sqlSessionTemplateASS")
    private SqlSessionTemplate sqlSessionTemplateASS;

    private Class<T> entityClass;

    private String pkName;                  //主键字段

    private String idName;                  //对应id名称

    private String seq;                     //当前主键

    private String tableName;

    private List<Pram> sqlParms;


    private List<Pram> selectSqlParms;

    private SqlUtil<T> sqlUtil;

    @SuppressWarnings("unchecked")
    public DaoImpl(){
        super();

        this.sqlUtil = new SqlUtil<T>();

        this.entityClass = (Class<T>) GenericsUtils.getSuperClassGenricType(this.getClass());

        this.sqlParms = this.sqlUtil.getPramList(this.entityClass);

        this.selectSqlParms = this.sqlUtil.getPramListOfSelect(this.entityClass);

        this.tableName = this.sqlUtil.getTableName(this.entityClass);

        //习惯统一用‘id’做约束了,所以这里我给固定死了,不想固定的话可以修改这里
        this.pkName = "id";

        this.idName = "id";

        this.seq = "id";

    }


    @Override
    public int addLocal(T po) {
        // TODO Auto-generated method stub

        String sql = "insert into " + tableName + " (";
        String prams = "";
        String values = "";

        List<Pram> pramList = SqlUtil.getPramListofStatic(po);

        int index = 0;
        for (int i = 0; i < pramList.size(); i++) {
            if (pramList.get(i).getValue() == null || (pramList.get(i).getValue() + "") .equals("0")) {
                continue;
            }else{
                if(index > 0){
                    prams += ",";
                    values += ",";
                }
                prams += pramList.get(i).getFile();
                Object value = pramList.get(i).getValue();
                if (value instanceof byte[] ) {
                    values += "'" + new String((byte[]) value) + "'";
                }else if(value instanceof String){
                    values += "'" + value + "'";
                }else{
                    values += value ;
                }

                index ++;
            }
        }
        sql += prams + ") value (" + values +");";

        SqlUtil.setFileValue(po, "id", nextId());

        logger.debug(sql);
        return sqlSessionTemplateASS.insert("addLocal", sql);

    }

    @Override
    public int add(T po) {
        // TODO Auto-generated method stub
        String sql = "insert into " + tableName + " (";
        String prams = "";
        String values = "";

        List<Pram> pramList = SqlUtil.getPramListofStatic(po);

        for (int i = 0; i < pramList.size(); i++) {
            prams += pramList.get(i).getFile();
            if (pramList.get(i).getValue() == null) {
                values += "null";
            }else{
                values += "'" + pramList.get(i).getValue() + "'";
            }

            if(i < pramList.size() -1){
                prams += ",";
                values += ",";
            }
        }
        sql += prams + ") value (" + values +");";

        SqlUtil.setFileValue(po, "id", nextId());

        return sqlSessionTemplateASS.insert("add", sql);
    }

    @Override
    public T get(PK id) {
        // TODO Auto-generated method stub
        String sql = "select ";
        for (int i = 0; i < selectSqlParms.size(); i++) {
            sql += selectSqlParms.get(i).getFile();
            if(i < selectSqlParms.size() -1){
                sql += ",";
            }else{
                sql += " ";
            }
        }
        sql += " from " + tableName + " where id='" + id + "';";
        Map<String, Object> resultMap = sqlSessionTemplateASS.selectOne(
                    "getById", sql);

        return handleResult(resultMap, this.entityClass);
    }

    @Override
    public Serializable getField(PK id, String fileName) {
        // TODO Auto-generated method stub
        String field = fileName;
        String tabField = "";
        Field f = sqlUtil.getField(this.entityClass, fileName);
        if (null == f) {
            logger.error("查询字段失败(无法找到" + this.entityClass + "中的" + fileName + "字段)");
        }
        FieldName annotation = f.getAnnotation(FieldName.class);
        if (null == annotation) {
            tabField = sqlUtil.toTableString(fileName) + " as " + fileName;
        }else{
            tabField = annotation.name() + " as " + fileName;
        }

        String sql = "select ";
        sql += tabField + " from " + tableName + " where id='" + id + "';";
        Map<String, Object> resultMap = sqlSessionTemplateASS.selectOne(
                "getFieldById", sql);
        return (Serializable) resultMap.get(fileName);
    }

    @Override
    public T get(WherePrams where) {
        // TODO Auto-generated method stub
        String sql = "select ";
        for (int i = 0; i < selectSqlParms.size(); i++) {
            sql += selectSqlParms.get(i).getFile();
            if(i < selectSqlParms.size() -1){
                sql += ",";
            }else{
                sql += " ";
            }
        }
        sql += "from " + tableName + where.getWherePrams() + ";";

        Map<String, Object> resultMap = sqlSessionTemplateASS.selectOne(
                "getByParm", sql);

        return handleResult(resultMap, this.entityClass);
    }

    @Override
    public Serializable getFile(WherePrams where, String fileName) {
        // TODO Auto-generated method stub
        String field = fileName;
        String tabField = "";
        Field f = sqlUtil.getField(this.entityClass, fileName);
        if (null == f) {
            logger.error("查询字段失败(无法找到" + this.entityClass + "中的" + fileName + "字段)");
        }
        FieldName annotation = f.getAnnotation(FieldName.class);
        if (null == annotation) {
            tabField = sqlUtil.toTableString(fileName) + " as " + fileName;
        }else{
            tabField = annotation.name() + " as " + fileName;
        }

        String sql = "select ";
        sql += tabField + " from " + tableName + where.getWherePrams() + ";";
        Map<String, Object> resultMap = sqlSessionTemplateASS.selectOne(
                "getFieldByParm", sql);
        return (Serializable) resultMap.get(fileName);
    }

    @Override
    public List<T> list(WherePrams where) {
        // TODO Auto-generated method stub

        String sql = "select ";
        for (int i = 0; i < selectSqlParms.size(); i++) {
            sql += selectSqlParms.get(i).getFile();
            if(i < selectSqlParms.size() -1){
                sql += ",";
            }else{
                sql += " ";
            }
        }
        sql += "from " + tableName + where.getWherePrams() + ";";

        List<Map<String, Object>> selectList = sqlSessionTemplateASS.selectList("selectList", sql);

        List<T> list = new ArrayList<>();
        for (Map<String, Object> map : selectList) {
            T t = handleResult(map, this.entityClass);
            list.add(t);
        }

        return list;

    }

    @Override
    public Serializable[] listFile(WherePrams where, String fileName) {
        // TODO Auto-generated method stub

        String field = fileName;
        String tabField = "";
        Field f = sqlUtil.getField(this.entityClass, fileName);
        if (null == f) {
            logger.error("查询指定字段集失败(无法序列化" + this.entityClass + "中的" + fileName + "字段)");
        }
        FieldName annotation = f.getAnnotation(FieldName.class);
        if (null == annotation) {
            tabField = sqlUtil.toTableString(fileName) + " as " + fileName;
        }else{
            tabField = annotation.name() + " as " + fileName;
        }

        String sql = "select ";
        sql += tabField + " from " + tableName + where.getWherePrams() + ";";
        List<Map<String, Object>> resultMap = sqlSessionTemplateASS.selectList("selectListField", sql);

        Serializable[] fields = new Serializable[resultMap.size()];

        for (int i = 0; i < resultMap.size(); i++) {
            if (null != resultMap.get(i)) {
                fields[i] =(Serializable) resultMap.get(i).get(fileName);
            }
        }

        return fields;
    }

    @Override
    public List<Map<String, Serializable>> listFiles(WherePrams where, String[] files) {
        // TODO Auto-generated method stub
        String tabField = "";
        int index = 1;
        for (String field : files) {
            Field f = sqlUtil.getField(this.entityClass, field);
            if (null == f) {
                logger.error("查询指定字段集失败(无法序列化" + this.entityClass + "中的" + field + "字段)");
            }
            FieldName annotation = f.getAnnotation(FieldName.class);
            if (null == annotation) {
                tabField += sqlUtil.toTableString(field) + " as " + field;
            }else{
                tabField += annotation.name() + " as " + field;
            }
            if (index < files.length) {
                tabField += ",";
            }

            index ++;
        }

        String sql = "select ";
        sql += tabField + " from " + tableName + where.getWherePrams() + ";";
        List<Map<String, Serializable>> resultMap = sqlSessionTemplateASS.selectList("selectListField", sql);

        return resultMap;
    }

    @Override
    public int updateLocal(T po) {
        // TODO Auto-generated method stub

        Serializable id = sqlUtil.getFileValue(po, "id");

        if(null == id){
            return 0;
        }
        String sql = "update " + tableName + " set ";
        List<Pram> prams = sqlUtil.getPramList(po);
        for (int i = 0; i < prams.size(); i++) {
            if(null != prams.get(i).getValue()){
                sql += prams.get(i).getFile() + "=";
                Object value = prams.get(i).getValue();
                if (value instanceof byte[] ) {
                    sql += "'" + new String((byte[]) value) + "'";
                }else if(value instanceof String){
                    sql += "'" + value + "'";
                }else{
                    sql += value ;
                }

//              sql += prams.get(i).getFile() + "='" + prams.get(i).getValue() + "'";
                if (i < prams.size() -1) {
                    sql += ",";
                }
            }
        }
        sql += " where id='" + id +"';";

        return sqlSessionTemplateASS.update("updateLocal", sql);
    }

    @Override
    public int update(T po) {
        // TODO Auto-generated method stub

        Serializable id = sqlUtil.getFileValue(po, "id");

        if(null == id){
            return 0;
        }
        String sql = "update " + tableName + " set ";

        List<Pram> prams = sqlUtil.getPramList(po);

        for (int i = 0; i < prams.size(); i++) {
            if(null != prams.get(i).getValue()){
                sql += prams.get(i).getFile() + "=";
                Object value = prams.get(i).getValue();
                if (value instanceof byte[] ) {
                    sql += "'" + new String((byte[]) value) + "'";
                }else if(value instanceof String){
                    sql += "'" + value + "'";
                }else{
                    sql += value ;
                }
//              sql += prams.get(i).getFile() + "='" + prams.get(i).getValue() + "'";
                if (i < prams.size() -1) {
                    sql += ",";
                }
            }else{
                sql += prams.get(i).getFile() + "=null";
                if (i < prams.size() -1) {
                    sql += ",";
                }
            }
        }
        sql += " where id='" + id +"';";

        return sqlSessionTemplateASS.update("update", sql);
    }

    @Override
    public int updateLocal(T po, WherePrams where) {
        // TODO Auto-generated method stub

        String sql = "update " + tableName + " set ";
        List<Pram> prams = sqlUtil.getPramList(po);
        for (int i = 0; i < prams.size(); i++) {
            if(null != prams.get(i).getValue()){
                sql += prams.get(i).getFile() + "=";
                Object value = prams.get(i).getValue();
                if (value instanceof byte[] ) {
                    sql += "'" + new String((byte[]) value) + "'";
                }else if(value instanceof String){
                    sql += "'" + value + "'";
                }else{
                    sql += value ;
                }
//              sql += prams.get(i).getFile() + "='" + prams.get(i).getValue() + "'";
                if (i < prams.size() -1) {
                    sql += ",";
                }
            }
        }
        sql += where.getWherePrams() +"';";

        return sqlSessionTemplateASS.update("updateLocalByPram", sql);

    }

    @Override
    public int update(T po, WherePrams where) {
        // TODO Auto-generated method stub

        String sql = "update " + tableName + " set ";
        Object[] o = new Object[sqlParms.size()];
        for (int i = 0; i < sqlParms.size(); i++) {
            if(null != sqlParms.get(i).getValue()){
                sql += sqlParms.get(i).getFile() + "=" + sqlParms.get(i).getValue();
                if (i < sqlParms.size() -1) {
                    sql += ",";
                }
            }else{
                sql += sqlParms.get(i).getFile() + "=null";
                if (i < sqlParms.size() -1) {
                    sql += ",";
                }
            }
        }
        sql += where.getWherePrams() + "';";

        return sqlSessionTemplateASS.update("updateByPram", sql);

    }

    @Override
    public int del(PK id) {
        // TODO Auto-generated method stub
        String sql = "delete from " + tableName + " where id=" + id;

        return sqlSessionTemplateASS.delete("deleteById", sql);
    }

    @Override
    public int del(WherePrams where) {
        // TODO Auto-generated method stub

        String sql = "delete from " + tableName + where.getWherePrams();

        return sqlSessionTemplateASS.delete("deleteByparm", sql);
    }

    @Override
    public List<Map<String, Object>> listBySql(String sql) {
        // TODO Auto-generated method stub

        List<Map<String, Object>> selectList = sqlSessionTemplateASS.selectList("selectBySql", sql);
        return selectList;
    }

    @Override
    public int excuse(String sql) {
        // TODO Auto-generated method stub
        return sqlSessionTemplateASS.update("excuse", sql);
    }

    @Override
    public long count(WherePrams where) {
        // TODO Auto-generated method stub

        String sql = "select count(*) from ";

        sql += tableName + where.getWherePrams();

        long count = sqlSessionTemplateASS.selectOne("selectCountByParm", sql);

        return count;
    }

    @Override
    public long size() {
        // TODO Auto-generated method stub
        String sql = "select count(*) from " + tableName;
        long count = sqlSessionTemplateASS.selectOne("selectCount", sql);
        return count;
    }

    @Override
    public boolean isExist(T po) {
        // TODO Auto-generated method stub
        WherePrams wherePrams = Method.createDefault();

        List<Pram> list = SqlUtil.getPramListofStatic(po);

        for (int i = 0; i < list.size(); i++) {
            if (i == 0) {
                wherePrams = Method.where(list.get(i).getFile(), C.EQ, (Serializable)list.get(i).getValue());
            }else{
                wherePrams.and(list.get(i).getFile(), C.EQ, (Serializable)list.get(i).getValue());
            }
        }


        return count(wherePrams) > 0;
    }

    @Override
    public boolean isExist(WherePrams where) {
        // TODO Auto-generated method stub
        return count(where) > 0;
    }

    @Override
    public List<T> in(String fileName, Serializable[] values) {
        // TODO Auto-generated method stub

        String sql = "select ";
        for (int i = 0; i < sqlParms.size(); i++) {
            sql += selectSqlParms.get(i).getFile();
            if(i < selectSqlParms.size() -1){
                sql += ",";
            }else{
                sql += " ";
            }
        }
        sql += "from " + tableName + " where " + fileName + " in ";
        String value = "(";
        for(int i = 0; i < values.length; i++){
            if(i < values.length -1){
                value += values[i] + ","; 
            }else{
                value += values[i] + ");"; 
            }
        }
        sql += value;

        List<Map<String, Object>> selectList = sqlSessionTemplateASS.selectList("selectIn", sql);

        List<T> list = new ArrayList<>();
        for (Map<String, Object> map : selectList) {
            T t = handleResult(map, this.entityClass);
            list.add(t);
        }

        return list;
    }

    private T handleResult(Map<String, Object> resultMap, Class<T> tClazz) {
        if (null == resultMap) {
            return null;
        }
        T t = null;
        try {
            t = tClazz.newInstance();
        } catch (InstantiationException e) {
            logger.error("/********************************");
            logger.error("实例化Bean失败(" + this.entityClass + ")!"
                    + e.getMessage());
            logger.error("/********************************");
        } catch (IllegalAccessException e) {
            logger.error("/********************************");
            logger.error("实例化Bean失败(" + this.entityClass + ")!"
                    + e.getMessage());
            logger.error("/********************************");
        }
        for (Map.Entry<String, Object> entry : resultMap.entrySet()) {
            String key = entry.getKey();
            Serializable val = (Serializable) entry.getValue();
            try {
                SqlUtil.setFileValue(t, key, val);
            } catch (Exception e) {
                // TODO: handle exception
                logger.error("/********************************");
                logger.error("/实例化Bean失败(" + this.entityClass + ")不能赋值到字段(" + key + "):"
                        + e.getMessage());
                logger.error("/********************************");
            }
        }
        return t;
    }

    /**
     * 获取某表的下一个Id
     */
    public long nextId(){
        String sql = "SELECT auto_increment FROM information_schema.`TABLES` WHERE TABLE_NAME='" + tableName + "'";
        Long idVal = sqlSessionTemplateASS.selectOne("fetchSeqNextval", sql);
        if (null == idVal) {
            logger.error("/********************************");
            logger.error("/获取id失败," + tableName + "表异常。请检查是否存在或者配为自增主键");
            logger.error("/********************************");
            return 0;
        }
        return idVal;

    }

}
		<p>
			<br />
		</p>
		<p style="text-indent:21.25pt;">
			大概就是这个样子,注解我是直接拷贝的之前的CRUD框架,同样,为了效率和兼容MyBaits,这里我直接在类上用了泛型,而不是在方法上用泛型。之前在方法上用了泛型机制,这样的优点就是,只需要实例化一个类就好了。大概调用方法是:
		</p>
		<p style="text-indent:21.25pt;">
//假设获取id为1的用户
UserPo user = get(UserPo.class,"id");
			<p>
				<br />
			</p>
			<p style="text-indent:21.25pt;">
				然而在效率上来说,则是大大的不好。因为每次方法调用时,都要将所传入的class进行解析,效率上大打折扣。在这里,我直接在类上加入了泛型,当一个Dao类初始化时,会自动对泛型字段进行解析,仅解析一次而已,之后每次使用这个Dao类的方法都是用解析好的资源。而不是每次调用方法就要反射一次。再配合Spring让其自动实例化,这样堪称完美。
			</p>
			<p style="text-indent:21.25pt;">
				那么,在使用过程中,则有了些许的改变,和Mybatis一样,需要些Dao,但是同样不用写实现类,准确的说,是直接集成已实现的Dao类。 <br />

加入我要写一个 UserDao,那么,我不需要写接口和 mapper 文件,直接这样搞:


/**
* 一个基于公用Dao的UserDao
*/
@Repository
public class UserDao extends Dao<UserPo, Integer> {

    //在这里,这个UserDao本身拥有了Dao的一些常用的增删改查方法。也可以重写或者增加一些特殊方法。
    public List<UserPo> listGirl(){

        //获取用户中的小姑娘,瞎写的。。
    }

    //再比如说我要重写一下list()这个方法
    public List<UserPo> list(WhereParms where){

        return super.list(where);
    }
}
				<p>
					<br />
				</p>
				<p style="text-indent:21.25pt;">
					仅此而已,比直接用插件生成dao层还要方便一些,至少我感觉是这样。 <br />

日然后,Service 层可以这么玩儿:


@Service
public class UserServiceImpl{

    @Resource
    private UserDao userDao;

        /*
        *根据姓名查找用户
        */
    public List<UserPo> listUser(String name){
        return userDao.list(Methor.where("name", C.Like, name));
    }
}
					<p>
						<br />
					</p>
					<p style="text-indent:21.25pt;">
						还有一些若干的小功能,比如说自动日志啦,(在Service层的任意方法中,加入@Log注解可以记录这个方法的进栈时间、执行时所接收的参数,执行时所出现的异常,出栈时间等等) <br />

再比如说自动事务(加入 @Transactional 注解后该方法拥有事务,一般和 @Log 一起用)


@Override
    @Transactional
    @Log
    public ResultBean delUser(int uId, int appId, AdminUser user) {
        // TODO Auto-generated method stub
        ResultBean resultBean = new ResultBean();
        resultBean.setResult(false);
        AdminApp app = adminAppDao.get(appId);
        if (null == app) {
            resultBean.setCode(1);
            resultBean.setMessage("App不存在");
            return resultBean;
        }
        if (app.getAdminUserId() != user.getId()) {
            resultBean.setCode(2);
            resultBean.setMessage("无权操作");
            return resultBean;
        }

        userFriendDao.del(Method.where("userId", C.EQ, uId));
        userFriendInfoDao.del(Method.where("userId", C.EQ, uId).or("friendId", C.EQ, uId));

        List<UserFriendGroup> list = userFriendGroupDao.list(Method.where("userId", C.EQ, uId));
        for (UserFriendGroup userFriendGroup : list) {
            userFriendDao.del(Method.where("friendGroupId", C.EQ, userFriendGroup.getId()));
            userFriendGroupDao.del(userFriendGroup.getId());
        }

        appUserDao.del(uId);
        app.setUserNum(app.getUserNum() - 1);
        adminAppDao.update(app);
        resultBean.setCode(0);
        resultBean.setMessage("删除成功");
        resultBean.setResult(true);
        return resultBean;
    }
						<p>
							<br />
						</p>
						<p style="text-indent:21.25pt;">
							—本次装逼结束,成功装完1个逼,成功捕获0个异常。成功率100% <br />

目前暂未发现明什么 Bug,阿海也再用这个封装的 mybatis 写一个自己的项目。等过段时间确定框架没有问题后,阿海再把该封装的 Jar 包以及源码发布。































  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    170 引用 • 414 回帖 • 400 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8208 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1458 回帖 • 109 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 15994792519

    大佬,大佬. 能把源码的 GitHub 地址发出来么。。 跪求。。。。。

推荐标签 标签

  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 137 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    4 引用 • 91 回帖
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖 • 1 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    281 引用 • 716 回帖
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    76 引用 • 37 回帖
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 555 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    21 引用 • 37 回帖 • 523 关注
  • 导航

    各种网址链接、内容导航。

    37 引用 • 168 回帖
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 12 关注
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 714 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    923 引用 • 936 回帖
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    285 引用 • 4482 回帖 • 658 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖 • 7 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    7017 引用 • 31714 回帖 • 220 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 446 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    14 引用 • 7 回帖 • 5 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    71 引用 • 1737 回帖 • 2 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 2 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    7 引用 • 26 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    69 引用 • 190 回帖 • 474 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 48 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 53 关注