瞎j8封装第二版之用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接口的更多相关文章
- 瞎j8封装第二版之数据层的封装
看了以前写的代码,对就是下面这个 手把手封装数据层之DataUtil数据库操作的封装 觉得以前写的代码好烂啊!!!,重新理了一下思路,写得更规范和简练,应该效率也会高很多,用了一下下午写的连接池(半废 ...
- 瞎j8封装第二版之数据库连接池
写得很蛋疼,本来想支持多线程的,奈何对多线程和连接池理解着实太菜: 所以,起码是能拿到连接了... 但是还是不太懂这个连接池 我也是半抄别人的,以后再搞一搞这个吧. 先是配置文件 理想是很丰满的,奈何 ...
- 一只菜鸟的瞎J8封装系列的目录
因为这是一个系列...也就是我们所说的依赖关系.后面很多方法都是基于我前面封装的工具来进行的,所以我列一个目录供大家参考... 一只菜鸟的瞎J8封装系列 一.手把手封装数据层之DButil数据库连接 ...
- 计算器-- 利用re模块 利用函数封装 第二版
import re remove_parentheses = re.compile('\([^()]+\)') def Remove_Parentheses(obj, s): # 找到内层的括号并且返 ...
- Idea mybatis maper接口与mapper.xml文件关联 会根据接口中的方法点在mxl中生成相应sql方法
- mapper.xml是怎样实现Dao层接口
上午写了一个简单的 从xml读取信息实例化一个Bean对象.下午就开始想mybatis是怎么通过xml文件来实现dao层接口的,一开始想直接用Class.forName(String name)然后调 ...
- java Domj4读取xml文件
先概括,再以代码形式给出. 获取节点: Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点 获取 标签: Element Document.get ...
- mybatis 基础(二) xml文件中的其他知识点
mybatis xml文件中一些标签的使用 此标签主要用作 配置 "别名" 如果实体类与数据库中字段名在不区分大小写的情况下相同的话, 那就不需要配置resultMap,因为mys ...
- MyBatis(七):使用注解替代xml文件
本文是按照狂神说的教学视频学习的笔记,强力推荐,教学深入浅出一遍就懂!b站搜索狂神说或点击下面链接 https://space.bilibili.com/95256449?spm_id_from=33 ...
随机推荐
- [读书笔记]javascript语言精粹'
人比较笨,以前只做项目,案例,然而一些javascript的很多理论不知道该怎么描述,所以最近开启一波读书之旅: 标识符 1.定义 标识符以字母开头,可能后面跟上一个或多个字母.数字或者下划线. 2. ...
- 圆形的ImageView
转载自gitHub的ImageView,因为本身就是可用的,也没什么好说的,拷贝回去用就是了,可以设置除了背景,还可以设置边框什么的,比起CardView设置圆角,功能更加强大. import and ...
- 微信小程序与Java后台的通信
一.写在前面 最近接触了小程序的开发,后端选择Java,因为小程序的代码运行在腾讯的服务器上,而我们自己编写的Java代码运行在我们自己部署的服务器上,所以一开始不是很明白小程序如何与后台进行通信的, ...
- 2807:两倍-poj
2807:两倍 总时间限制: 1000ms 内存限制: 65536kB 描述 给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍. 比如给定1 4 ...
- Java第二季
1.封装 (1)概念 将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. (2)封装的实现步骤 2.Java中的访问修饰符 3.继承 (1)Ja ...
- Python之可变类型与不可变类型
Python常见的数据类型有:数字 字符串 元组 列表 字典 不可变类型:数字 字符串 元组 可变类型: 列表 字典 a = 100 b = [100] def num1(x): x += x pri ...
- 命令模式(Command)
命令模式(Command) 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互 ...
- Python中的选择排序
选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理如下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大 ...
- 【深度学习系列】用PaddlePaddle和Tensorflow实现经典CNN网络Vgg
上周我们讲了经典CNN网络AlexNet对图像分类的效果,2014年,在AlexNet出来的两年后,牛津大学提出了Vgg网络,并在ILSVRC 2014中的classification项目的比赛中取得 ...
- 组件嵌套时报:Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
在组件嵌套的过程中,报了一个错误: 这里报错的原因是:vue的组件(模板)只能有一个根节点,即.vue文件中的<template>标签下只能有一个子元素. 因此,建议大家在写.vue组件的 ...