sql xml读取row的属性_SSM框架(三):自定义一个支持xml和注解配置mybatis框架,进行查询所有操作...

将昨天的例子:SSM框架(一):mybatis简单介绍和入门案例分析,我们移除pom.xml中的mybatis相关的坐标后,自定义一个mabatis框架,实现 "select * from user" 的功能。

最终我们的目录结构如下:

src
├─main
│  ├─java
│  │  └─cn
│  │      └─figo
│  │          ├─dao
│  │          ├─domain
│  │          └─mybatis
│  │              ├─annotation
│  │              ├─cfg
│  │              ├─io
│  │              ├─sqlsession
│  │              │  ├─defaults
│  │              │  └─proxy
│  │              └─utils
│  └─resources
│      └─cn
│          └─figo
│              └─dao
└─test
    └─java
        └─cn
            └─figo
                └─test

当通过注解配置持久化层后并修改主配置文件中的mapper属性为class后,我们可以通过自定义框架的注解进行查询:

1b1e2113d7bb8d0298b51a59e8ddf7a6.png

cba817d9af08ee34d3a770f56870ae95.png

最终输出如下:

b55f2bfc163d9cfc87416588f884756a.png

当通过xml配置持久化层后并修改主配置文件中的mapper属性为resource后,我们可以通过自定义框架的注解进行查询:

6bdb42e1f9b300a393c87c1470a019e4.png

156690114dbdd622b994c3060998166f.png

最终输出如下:

3c18e3e56b2b44cfd38c665fc6943ac8.png

我们定义的mybatis中的所有类、接口、注解如下图所示:

db760ebc736310ca453e6673d3c8a688.png

1、使用类加载器读取配置文件的类:Resources

package cn.figo.mybatis.io;

import java.io.InputStream;

/**
 * @Author Figo
 * @Date 2019/10/28 21:34
 * 使用类加载器读取配置文件的类
 */
public class Resources {

    /**
     * 根据传入的参数,获取一个字节输入流
     * @param filePath
     * @return
     */
    public static InputStream getResourceAsStream(String filePath){
        return Resources.class.getClassLoader().getResourceAsStream(filePath);
    }
}

2、用于保存数据库和映射配置信息的实体类:Configuration

package cn.figo.mybatis.cfg;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author Figo
 * @Date 2019/10/28 21:58
 * 自定义mybatis的配置类
 */
public class Configuration {

    private String driver;
    private String url;
    private String username;
    private String password;

    // 用于存放从映射xml中读取的 SQL语句和结果类型的全限定类名,key为 dao的全限定类名.方法名
    private Map<String,Mapper> mappers = new HashMap<String,Mapper>();

    public Map<String, Mapper> getMappers() {
        return mappers;
    }

    //此处需要使用追加的方式
    public void setMappers(Map<String, Mapper> mappers) {
        this.mappers.putAll(mappers);
    }

    // 其他 getter 和 setter 省略
}

3、用于保存sql语句和封装数据全限定类名的映射信息的实体类:Mapper

package cn.figo.mybatis.cfg;

/**
 * @Author Figo
 * @Date 2019/10/28 22:01
 * 用于封装执行的SQL语句和结果类型的全限定类名
 */
public class Mapper {
    //SQL
    private String queryString;
    //实体类的全限定类名
    private String resultType;

    // getter 和 setter 省略
}

4、构建工厂的构建者类:SqlSessionFactoryBuilder

package cn.figo.mybatis.sqlsession;

import cn.figo.mybatis.cfg.Configuration;
import cn.figo.mybatis.sqlsession.defaults.DefaultSqlSessionFactory;
import cn.figo.mybatis.utils.XMLConfigBuilder;

import java.io.InputStream;

/**
 * @Author Figo
 * @Date 2019/10/28 21:40
 * 用于创建一个SqlSessionFactory对象
 */
public class SqlSessionFactoryBuilder {

    /**
     * 根据参数的字节输入流来构建一个SqlSessionFactory工厂
     * @param config
     * @return
     */
    public SqlSessionFactory build(InputStream config){
        Configuration cfg = XMLConfigBuilder.loadConfiguration(config);
        return new DefaultSqlSessionFactory(cfg);
    }
}

5、工厂接口和实现类:SqlSessionFactory 、DefaultSqlSessionFactory

package cn.figo.mybatis.sqlsession.defaults;

import cn.figo.mybatis.cfg.Configuration;
import cn.figo.mybatis.sqlsession.SqlSession;
import cn.figo.mybatis.sqlsession.SqlSessionFactory;

/**
 * @Author Figo
 * @Date 2019/10/28 22:19
 * SqlSessionFactory接口的实现类
 */
public class DefaultSqlSessionFactory implements SqlSessionFactory {

    private Configuration cfg;
    public DefaultSqlSessionFactory(Configuration cfg){
        this.cfg = cfg;
    }
    /**
     * 用于创建一个新的操作数据库对象
     * @return
     */
    @Override
    public SqlSession openSession() {
        return new DefaultSqlSession(cfg);
    }
}

6、用于创建代理对象的接口和实现类:SqlSession、DefaultSqlSession

package cn.figo.mybatis.sqlsession.defaults;

import cn.figo.mybatis.cfg.Configuration;
import cn.figo.mybatis.sqlsession.SqlSession;
import cn.figo.mybatis.sqlsession.proxy.MapperProxy;
import cn.figo.mybatis.utils.DataSourceUtil;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @Author Figo
 * @Date 2019/10/28 22:24
 * SqlSession接口的实现类
 */
public class DefaultSqlSession implements SqlSession {

    // Configuration 对象中包括数据库信息和映射信息
    private Configuration cfg;
    private Connection connection;

    public DefaultSqlSession(Configuration cfg){
        this.cfg = cfg;
        connection = DataSourceUtil.getConnection(cfg);
    }

    /**
     * 用于创建代理对象
     * @param daoInterfaceClass dao的接口字节码
     * @param <T>
     * @return
     */
    @Override
    public <T> T getMapper(Class<T> daoInterfaceClass) {
        Class[] x = new Class[]{daoInterfaceClass};
        return (T)Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
                new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(),connection));
    }

    /**
     * 用于释放资源
     */
    @Override
    public void close() {
        if (connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

7、用于创建代理对象时增强功能InvocationHandler实现类:MapperProxy

package cn.figo.mybatis.sqlsession.proxy;

import cn.figo.mybatis.cfg.Mapper;
import cn.figo.mybatis.utils.Executor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Map;

/**
 * @Author Figo
 * @Date 2019/10/28 22:31
 * 用于创建代理对象时增强功能
 */
public class MapperProxy implements InvocationHandler {

    // map的key是全限定类名+方法名
    private Map<String, Mapper> mappers;
    private Connection conn;

    public MapperProxy(Map<String,Mapper> mappers,Connection conn){
        this.mappers = mappers;
        this.conn = conn;
    }

    /**
     * 用于对方法进行增强的,我们的增强其实就是调用selectList方法
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        String className = method.getDeclaringClass().getName();
        String key = className + "." + methodName;
        Mapper mapper = mappers.get(key);
        if (mapper == null){
            throw new IllegalArgumentException("传入的参数有误");
        }
        return new Executor().selectList(mapper,conn);
    }
}

8、用于解析配置文件的工具类:XMLConfigBuilder

9、用于获取数据库连接的工具类:DataSourceUtil

10、用于执行SQL语句,并且封装结果集的工具类:Executor

其中8、9、10工具类省略,push至github

YourFigo/javaSSM​github.com
c640a72f8289c81c02e2811e29d8aea9.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值