瞎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 ...
随机推荐
- ssh密钥登录
一.生成密钥对(两种方式)并配置 方式1:使用ssh-keygen(1)生成并配置 (1)生成密钥对 [root@iZwz9catu2mrq92b07d1d0Z ~]# ssh-keygen -t r ...
- EXTtreeGrid分页
这个东西整了两天,关键在于要两个stroe,之所以要两个因为treestroe在分页的时候接受不了返回的总行数,不过有个问题就是第二页分页后显示在没有根节点的行层级显示不是那木明显: -------- ...
- WPF开发的彩票程序(练手好例子) 附源码
前言 WPF是.NET最新的界面开发库,开发界面非常灵活!但是学习WPF难度也非常大. 应朋友之邀,编写了一个小程序.程序虽小,五脏俱全,WPF开发的灵活性可窥见一斑. 对于新手学习有很好的借鉴意义, ...
- Java基础概念1
一.Java数据类型 1.byte 字节型 1byte = 8bit 表示数范围:-2^7~2^7-1(-128~127): 2.short 短整型 2 byte = 16bit 表示数范围:-2^1 ...
- 爬起点小说day03
# 把所有类别的前3页的小说爬取下来 import scrapyfrom scrapy.http import Requestfrom time import sleepfrom qidianNove ...
- Elasticsearch中Head插件的使用
在学习Elasticsearch的过程中,必不可少需要通过一些工具查看es的运行状态以及数据.如果都是通过rest请求,未免太过麻烦,而且也不够人性化.此时,head可以完美的帮助你快速学习和使用El ...
- POJ1837--二维背包
Balance Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 13525 Accepted: 8474 Description ...
- oracle中 常用的 join on 相关和 集合运算的总结
sql常用联合查询的 join on . left join(左连接) . right join (右连接).inner join (等值连接)以及常用的集合运算有:union.unionall.mi ...
- ArcGIS jsAPI (4.x)本地部署字体符号乱码
在下载了新版arcigs 的 JS API 后,每次部署在IIS中都会出现部件字体乱码的问题,需配置响应标头和添加文件映射 一. HTTP响应标头配置 在 IIS 中的 HTTP响应标头 中加入以下配 ...
- mac ox下android 通过battery-historian进行电量分析
简单介绍下如何用battery-historian进行电量分析,因为battery-hostorian是基于go语言的框架,所以需要安装go 1.安装go 2.配置go环境变量到.bash_profi ...