瞎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 ...
随机推荐
- IMDB TOP 250爬虫
这个小学期Python大作业搞了个获取IMDB TOP 250电影全部信息的爬虫.第二次写爬虫,比在暑假集训时写的熟练多了.欢迎大家评论. ''' ************************** ...
- php 的开发工具
通过上篇我们已经配置好了php的开发环境,我们就可以在这个模拟的环境下运行我们编写的php代码了. 在编写代码前,先安装一个自己喜欢的代码编辑器. 1.sublime text Sublime Tex ...
- OPENCV3——从入门到出门
跑第一个程序的时候经过坑爹的各种设置终于能用了. 如果遇到问题就谷歌或者百度,大牛的博客会给出解决方案的. vs2010+opencv3 目标:把书上的程序挨个敲一遍跑一遍. 现在已经跑了七章了,还有 ...
- 关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别
轮播中大多会选择mouseover和mouseout 这个时候是没有任何问题的 但当遇到有css3动画的时候,会发现移入移出过快 动画还没加载完成就需要执行下一个动画,完了动画样式就错乱了. 这时候 ...
- buttongroup中content一次性加载的解决方法
buttongroup一次性加载所有内容的解决方法 如下图所示: 第一步: 设置windowcontainer的autoLoad属性为false(默认情况下autoLoad属性为true,所以会加载所 ...
- jQuery中使用$.each()遍历后台响应的json字符串问题
今天在做练习项目的时候,使用$.each()方法遍历后台传过来的json字符串时,chrome浏览器中发现如下问题 Cannot use 'in' operator to search for 'l ...
- Linux系统bashshell之别名
1.别名的查看: 命令查看:alias 配置文件查看:cat ~/.bashrc 2:别名设置: alias cdnet="cd /etc/sysconfig/network-scri ...
- Python入门 - 控制结构
python控制结构有:for循环, while循环, if条件语句,下面我们直接上代码. 一.for循环 a = range(5) for x in a : print(x) 0 1 2 3 4二. ...
- Android7.0 PowerManagerService 之亮灭屏(一)
本篇从按下power按键后,按键事件从InputManagerService 传到PhoneWindowManager.java开始分析power 按键做屏幕亮灭过程的分析,关于power 按键的其他 ...
- CCF-201412-3-集合竞价
问题描述 试题编号: 201412-3 试题名称: 集合竞价 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 某股票交易所请你编写一个程序,根据开盘前客户提交的订单来确定某特定 ...