瞎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 ...
随机推荐
- AIO5系统中-打印样式常见问题处理
1.为什么我的报表没有数据显示? 答:请看一下报表是否有绑定数据源,有添加查询,如果这些都做了,请看下主项数据的数据源有没有绑定,这些都绑定了,就会有数据的显示. 2.为什么我做的报表分组很乱? 答: ...
- Rigidbody组件及相关API
Rigidbody:刚体组件,物理类.(与Rigidbody组件相关的代码尽量都写在FixedUpdate()方法中,如果写在Update()中有可能会卡顿) 属性:Mass:质量. ...
- JQuery之事件冒泡
JQuery 提供了两种方式来阻止事件冒泡. 方法一:event.stopPropagation(); $("#div1").mousedown(function(event){ ...
- ExpandableListView使用
相关博客 ExpandableListView使用 博客内容记录 场景 有时候,使用ListView并不能满足应用程序所需要的功能.有些应用程序需要多组ListView,这时候我们就要使用一种新的控件 ...
- jQuery常用事件及扩展
jquery中的常用事件 blur([[data],fn]) --失去焦点触发(鼠标)focus([[data],fn]) --得到焦点触发(鼠标)change([[data],fn]) - ...
- Redis各个数据类型的使用场景
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). Redis列表命令 参考:http://www.r ...
- 详解spl_autoload_register()函数
一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.class.php <?php class ...
- 反射---hasattr、getattr、setattr、delattr
class Foo: f = "类的静态变量" def __init__(self,name,age): self.name = name self.age = age def s ...
- oracle 数据库中的序列
序列是什么,通俗点说,序列就是按照一定顺序进行排列,序列会自动给你递增,生成唯一的序列号: oracle数据库不同于sqlServer数据库,oracle数据库中是没有自增长列,使用的是sequenc ...
- 基于AOE网的关键路径的求解
[1]关键路径 在我的经验意识深处,“关键”二字一般都是指临界点. 凡事万物都遵循一个度的问题,那么存在度就会自然有临界点. 关键路径也正是研究这个临界点的问题. 在学习关键路径前,先了解一个AOV网 ...