瞎j8封装第二版之用xml文件来代理dao接口

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

    模仿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

原文地址:https://www.cnblogs.com/yeyeck/p/8159359.html

时间: 2024-10-08 23:01:23

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

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

看了以前写的代码,对就是下面这个 手把手封装数据层之DataUtil数据库操作的封装 觉得以前写的代码好烂啊!!!,重新理了一下思路,写得更规范和简练,应该效率也会高很多,用了一下下午写的连接池(半废品...) 瞎j8封装第二版之数据库连接池 下面直接上代码,代码很好理解,就是用了简单的反射,注解的部分我都写了注释 package jdbc; import util.StringUtil; import java.lang.reflect.Field; import java.lang.refl

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

写得很蛋疼,本来想支持多线程的,奈何对多线程和连接池理解着实太菜: 所以,起码是能拿到连接了... 但是还是不太懂这个连接池 我也是半抄别人的,以后再搞一搞这个吧. 先是配置文件 理想是很丰满的,奈何现实... jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=true jdbc.username

阿里面试题:Mybatis中的Dao接口和XML文件里的SQL是如何建立关系的?

一.解析XML首先,Mybatis在初始化SqlSessionFactoryBean的时候,找到mapperLocations路径去解析里面所有的XML文件,这里我们重点关注两部分.1.创建SqlSourceMybatis会把每个SQL标签封装成SqlSource对象.然后根据SQL语句的不同,又分为动态SQL和静态SQL.其中,静态SQL包含一段String类型的sql语句:而动态SQL则是由一个个SqlNode组成. 假如我们有这样一个SQL: <select id="getUserB

Dom4j读取xml文件——JAVA

前几天,用Dom4j写了三个版本的读取XML文件,现在分享下. 第一版本: XML: <?xml version="1.0" encoding="UTF-8"?> <do-config> <do path="User/adduser" type="UserPackage.UserServlet"> <forward name="Success">AddSucc

Android第二期 - 中国天气预报xml解析版(111)

实习比较忙,也时间写了,就记录一下自己的代码成长吧,希望能帮到你. MainActivity部分: package com.sbs.weather; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.http.HttpEntity; import org.apache.htt

阅读《代码大全》(第二版)体会小结

这一次阅读了著名的<代码大全>(第二版).全书虽然章节众多,但是主要就是几个大部分,这些部分我大多有一些浅显的了解但还未深入,当然也有一些全新的体验,例如表驱动法.全书内容丰富而详细,我在阅读的其中问题并不是太多,只不过很多的内容都觉得了解的还太浅,需要更多的实践以及阅读去体会.在这里记录下的也就是一些自己的体会,主要是对书中一些论断的不同看法与讨论,大部分是关于面向对象和结构化设计的内容:以及对于全新接触的表驱动法的学习体会. Question 1: “7.1 创建子程序的正当理由”中,提到

js仿百度文库文档上传页面的分类选择器_第二版

仿百度文库文档上传页面的多级联动分类选择器第二版,支持在一个页面同时使用多个分类选择器: 此版本把HTML,CSS,以及图片都封装到"category.js"中,解决因文件路径找不到样式及图片的问题: 源码下载地址:http://download.csdn.net/detail/testcs_dn/7290577 初始状态,一个页面使用两个,可以初始化之前选中的分类: 选择状态: 当选中一个分类后,会触发"onChange"事件,如上图中的"您选择的分类编

解析服务器端回传 XML 文件并封装为对象

起因 项目的上游数据对接方通过XML文件与主体项目进行通信,获取其XML的方法为通过HTTP的GET请求返回XML文件,之前还未遇到过这种传递方式,就稍微查了一下资料,写了一个出来,如果你也有类似的需求,可供参考. 正文 整个"接收-存储-查询-赋值"由两个模块组成,即"接收-存储"与"查询-赋值",配合一个用于封装的实体类与一个提高复用性的"Date-String"转换工具类. 整体的思路很简单,首先用java的"

第一行代码第二版(郭霖著)笔记之第三章(UI开发的点点滴滴)

1. 常用控件 Button 当我们设置Button的内容为Hello的时候,系统会对Hello的所有英文字母进行大写转换,显示在屏幕上为HELLO,如果不想要这个效果,设置属性android:textAllCaps为false即可,代码如下: <Button android:textAllCaps="false" android:text="Hello" android:layout_width="match_parent" androi