也是重新整理了之前的那篇

    模仿Mybatis用map

per.xml实现Dao层接口的功能

话不多说直接上代码

首先是结构

依赖pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>yebatis</groupId>
    <artifactId>com.yck.yebatis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.42</version>
        </dependency>
    </dependencies>

</project>

一些基本类

用来封装一个dao信息的Mapper类

package com.yck.yebaitis;

import java.util.List;

public class Mapper {

    private String mapperClass;
    private List<Function> functions;

    public String getMapperClass() {
        return mapperClass;
    }

    public void setMapperClass(String mapperClass) {
        this.mapperClass = mapperClass;
    }

    public List<Function> getFunctions() {
        return functions;
    }

    public void setFunctions(List<Function> functions) {
        this.functions = functions;
    }
}

封装一条方法信息的Function类

package com.yck.yebaitis;

public class Function {
    private String name;
    private String type;
    private Class<?> resultClass;
    private String sql;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Class<?> getResultClass() {
        return resultClass;
    }

    public void setResultClass(Class<?> resultClass) {
        this.resultClass = resultClass;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }
}

常量

package com.yck.yebaitis;

public class FunctionConstants {
    public static final String ADD = "add";
    public static final String DELETE = "delete";
    public static final String UPDATE = "update";
    public static final String SELECT = "select";

}

实现功能的DaoFactory

package com.yck.yebaitis;

import com.yck.jdbc.DataUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.yck.util.StringUtil;
import com.yck.exception.NoConfigFileException;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

public class DaoFactory {

    private static final String configPath = "src/dao/mapper";
    private static DaoFactory instance;

    private DaoFactory() {
    }

    public static DaoFactory getInstance() {
        if (instance == null) {
            synchronized (DaoFactory.class) {
                if (instance == null)
                    instance = new DaoFactory();
            }
        }
        return instance;
    }

    public Map<String, Object> getDaoMap() {
        Map<String, Object> map = null;
        try {
            File[] files = getAllFiles();
            map = new HashMap<>(files.length);
            for (File file : files) {
                Mapper mapper = readerMapper(file);
                Object obj = implDao(mapper);
                map.put(mapper.getMapperClass(), obj);

            }
        } catch (NoConfigFileException | ClassNotFoundException | DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }

    private Object implDao(Mapper mapper) throws ClassNotFoundException {
        ClassLoader classLoader = DaoFactory.class.getClassLoader();
        final Mapper temp = mapper;
        //加载一个接口类
        Class<?> interfaze;
        interfaze = classLoader.loadClass(mapper.getMapperClass());

        /*
        代理实现方法
        之前我是理解错了,我以为是在执行下面这个方法时,就已经实现了类似我们自己写一个DaoImpl,其实它就只是返回了一个代理类实例
         */
        return Proxy.newProxyInstance(classLoader, new Class[]{interfaze}, new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) {
                List<Function> functions = temp.getFunctions();
                for (Function func : functions) {
                    if (func.getName().equals(method.getName())) {
                        if (func.getType().equals(FunctionConstants.SELECT)) {
                            if (method.getReturnType().equals(List.class)) {
                                return DataUtil.queryForList(func.getSql(), func.getResultClass(), args);
                            } else {
                                return DataUtil.queryForObject(func.getSql(), func.getResultClass(), args);
                            }
                        } else {
                            return DataUtil.excuteUpdate(func.getSql(), args);
                        }
                    }
                }
                return null;
            }
        });
    }

    private File[] getAllFiles() throws NoConfigFileException {

        FileFilter fileFilter = new FileFilter() {
            public boolean accept(File pathname) {
                String fileName = pathname.getName().toLowerCase();
                return fileName.endsWith(".xml");
            }
        };
        File configPath = new File("src/mapper");
        File[] files = configPath.listFiles(fileFilter);
        if (files == null || files.length == 0) {
            throw new NoConfigFileException("file not find");
        }
        return files;
    }

    private Mapper readerMapper(File file) throws DocumentException, ClassNotFoundException {
        SAXReader reader = new SAXReader();
        Mapper mapper = new Mapper();

        Document doc = reader.read(file);
        Element root = doc.getRootElement(); //读取根节点 即dao节点
        mapper.setMapperClass(root.attributeValue("class").trim()); //把dao节点的class值存为接口名
        List<Function> list = new ArrayList<>(); //用来存储方法的List
        for (Iterator<?> rootIter = root.elementIterator(); rootIter.hasNext(); ) //遍历根节点下所有子节点
        {
            Function fun = new Function();    //用来存储一条方法的信息
            Element e = (Element) rootIter.next();
            String type = e.getName().trim();
            switch (type) {
                case FunctionConstants.ADD:
                    fun.setType(FunctionConstants.ADD);
                    break;
                case FunctionConstants.DELETE:
                    fun.setType(FunctionConstants.DELETE);
                    break;
                case FunctionConstants.UPDATE:
                    fun.setType(FunctionConstants.UPDATE);
                    break;
                case FunctionConstants.SELECT:
                    fun.setType(FunctionConstants.SELECT);
                    break;
                default:
                    continue;
            }
            fun.setName(e.attributeValue("id").trim());
            fun.setSql(e.getText().trim());
            String resultType = e.attributeValue("resultType");
            if (!StringUtil.isBlank(resultType)) {
                fun.setResultClass(Class.forName(resultType));
            }
            list.add(fun);
        }
        mapper.setFunctions(list);
        return mapper;
    }
}

测试用类

 

实现IUserDao的xml文件就是最底下的userdao.xml

<?xml version="1.0" encoding="UTF-8"?>
<dao id="userdao" class="dao.IUserDao">

    <select id="selectById" resultType ="po.User">
        select * from t_user where id = ?
    </select>

    <update id="updateName">
        update t_user set name = ? where id = ?
    </update>

    <delete id="deleteById">
        delete from t_user where id=?
    </delete>

    <insert id="add">
        insert into t_user(name,age,score,create_time,update_time)
        values(?,?,?,now(),now());
    </insert>

    <select id="getAll" resultType = "po.User">
        select * from t_user;
    </select>

</dao>

测试代码

import com.yck.yebaitis.DaoFactory;
import dao.IUserDao;
import po.User;

import java.util.List;
import java.util.Map;

public class Test {

    public static void main(String[] args) {

        Map<String,Object> daoMap = DaoFactory.getInstance().getDaoMap();
        IUserDao dao = (IUserDao) daoMap.get("dao.IUserDao");
        List<User>  users = dao.getAll();
        System.out.println("查询多条记录:"+users);
        System.out.println("*******************************************");

        User user = dao.selectById(2);
        System.out.println("查询一条记录:"+user);
        System.out.println("*******************************************");

        int i = dao.updateName("二傻",2);
        System.out.println("更新一条记录:"+i);
        System.out.println("*******************************************");

        List<User> userList = dao.getAll();
        System.out.println("更新一条记录后查询所有记录:"+user);
        System.out.println("*******************************************");

    }
}

测试结果

大王让我写代码 23:15:19

瞎j8封装第二版之用xml文件来代理dao接口的更多相关文章

  1. 瞎j8封装第二版之数据层的封装

    看了以前写的代码,对就是下面这个 手把手封装数据层之DataUtil数据库操作的封装 觉得以前写的代码好烂啊!!!,重新理了一下思路,写得更规范和简练,应该效率也会高很多,用了一下下午写的连接池(半废 ...

  2. 瞎j8封装第二版之数据库连接池

    写得很蛋疼,本来想支持多线程的,奈何对多线程和连接池理解着实太菜: 所以,起码是能拿到连接了... 但是还是不太懂这个连接池 我也是半抄别人的,以后再搞一搞这个吧. 先是配置文件 理想是很丰满的,奈何 ...

  3. 一只菜鸟的瞎J8封装系列的目录

    因为这是一个系列...也就是我们所说的依赖关系.后面很多方法都是基于我前面封装的工具来进行的,所以我列一个目录供大家参考... 一只菜鸟的瞎J8封装系列  一.手把手封装数据层之DButil数据库连接 ...

  4. 计算器-- 利用re模块 利用函数封装 第二版

    import re remove_parentheses = re.compile('\([^()]+\)') def Remove_Parentheses(obj, s): # 找到内层的括号并且返 ...

  5. Idea mybatis maper接口与mapper.xml文件关联 会根据接口中的方法点在mxl中生成相应sql方法

  6. mapper.xml是怎样实现Dao层接口

    上午写了一个简单的 从xml读取信息实例化一个Bean对象.下午就开始想mybatis是怎么通过xml文件来实现dao层接口的,一开始想直接用Class.forName(String name)然后调 ...

  7. java Domj4读取xml文件

    先概括,再以代码形式给出. 获取节点: Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点 获取 标签: Element Document.get ...

  8. mybatis 基础(二) xml文件中的其他知识点

    mybatis xml文件中一些标签的使用 此标签主要用作 配置 "别名" 如果实体类与数据库中字段名在不区分大小写的情况下相同的话, 那就不需要配置resultMap,因为mys ...

  9. MyBatis(七):使用注解替代xml文件

    本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...

随机推荐

  1. Python案例分享

    1.过桥(爬金字塔): 1 i = 1 2 while i <= 9: 3 if i < 6: 4 j = 0 5 while j < i: 6 print('*',end=' ') ...

  2. SurfaceView 及相关概念

    ============================================================= SurfaceView=========================== ...

  3. 《用Java写一个通用的服务器程序》02 监听器

    在一个服务器程序中,监听器的作用类似于公司前台,起引导作用,因此监听器花在每个新连接上的时间应该尽可能短,这样才能保证最快响应. 回到编程本身来说: 1. 监听器最好由单独的线程运行 2. 监听器在接 ...

  4. head first python菜鸟学习笔记(第三章)

    1.os.chdir()切换到指定目录下,os.getcwd(),得到当前目录. >>> import os>>> os.chdir('D:\\CodeDocume ...

  5. Java 将两个有序数组合成为一个有序数组

    基本思路 1.如果其中一个数组的元素均大于另一个数组的元素,则可以直接组合,不用拆分. 即:其中一个数组的第一个元素大于或者小于另一个数组的最后一个元素 2.若不满足1中的情况,则表明数组需要拆分,拆 ...

  6. 微信官方团队放出了UI库,看来以后前端还要学WeChatUI了,哈哈

    已经在github上发布,网址如下:https://github.com/weui/weui

  7. Git命令汇总(补充篇)

    上一篇<Git命令汇总基础篇>总结了使用Git的基本命令,这一篇作为补充主要给大家讲一些平时使用中的技巧和总结 . 学会了这些命令,已经基本解决了使用Git中大部分问题. 1.gitign ...

  8. mysql数据库插入数据获取自增主键的三种方式(jdbc PreparedStatement方式、mybatis useGeneratedKeys方式、mybatis selectKey方式)

    通常来说对于mysql数据库插入数据获取主键的方法是采用selectKey的方式,特别是当你持久层使用mybatis框架的时候. 本文除此之外介绍其它两种获取主键的方式. 为了方便描述我们先建一张my ...

  9. And【sql语句之为何用and一个字段两个值得不到表中的数据】

    一.[一个表的一个字段的多个条件用and连接] 用and是查不到值的, and是多个条件同时成立, 也就是一个字段是不能同时等于两个值的. '; 二[相同两个表的两个相同字段的查询用and连接] '; ...

  10. 深入浅出了解frame和bounds

    frame frame的官方解释如下: The frame rectangle, which describes the view's location and size in its supervi ...