Mybatis框架的自定义补全

用于XML最基础的配置

因为读取xml信息的代码编写
SqlMapConfig.xml的mappers//mapper中只能用Resource映射
AccountByIdDao.xml中要有返回类型的全限定类名

测试类基本步骤:

public class Self_defindedTest {
    public static void main(String[] args) throws Exception{
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);//多态,继承接口SqlSessionFactory
        SqlSession session = factory.openSession();//多态,继承接口SqlSession
        //注意,增删改方法需要提交事务,openSession()可添加true实现提交事务,此自定义并未实现
        AccountByIdDao byIdDao = session.getMapper(AccountByIdDao.class);
        List<Account> all = byIdDao.findAll();
        for (Account account : all){
            System.out.println(account);
        }
        session.close();
        is.close();
    }
}

根据传入的参数获取字节输入流

InputStream is = Resources.getResourceAsStream(“sqlMapConfig.xml”);

public class Resources {
   		
   		 public static InputStream getResourceAsStream(String filePath){
        return Resources.class.getClassLoader().getResourceAsStream(filePath);
    }
}

根据字节输入流建立工厂**

此处省略XMLConfigBuilder代码

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

public class SqlSessionFactoryBuilder {

    public SqlSessionFactory build(InputStream is){
        Configuration cfg = XMLConfigBuilder.loadConfiguration(is);
        return new DefaultSqlSessionFactory(cfg);//到下一步环节
    }
}

**Configuration来表示读取到的文件的信息 **

Configuration cfg = XMLConfigBuilder.loadConfiguration(is);

public class Configuration {
    private String driver;
    private String url;
    private String username;
    private String password;
    private Map<String,Mapper> mappers = new HashMap<String, Mapper>();
    
//此处省略get和set方法的构建
}

Mapper封装执行的SQL语句和结果类型的全限定类名

Map<String,Mapper> mappers = new HashMap<String, Mapper>();

public class Mapper {
    private String queryString;
    private String resultType;
    //略set,get
    }

将文件信息给代理类创建新的数据库对象

SqlSession session = factory.openSession();//基础步骤

return new DefaultSqlSessionFactory(cfg);

public class DefaultSqlSessionFactory  implements SqlSessionFactory{
    private Configuration cfg;

    public DefaultSqlSessionFactory(Configuration cfg) {
        this.cfg = cfg;
    }

    @Override
    public SqlSession openSession() {
        return new DefaultSqlSession(cfg);//转到下一步环节
    }
}

输入代理对象类对其增强

AccountByIdDao byIdDao = session.getMapper(AccountByIdDao.class);
session.close(); //基础步骤

return new DefaultSqlSession(cfg);

public class DefaultSqlSession implements SqlSession{
    private Configuration cfg;
    private Connection connection;
    public DefaultSqlSession(Configuration cfg) {
        this.cfg = cfg;
        connection = DataSourceUtil.getConnection(cfg);
    }

    @Override
    public <T> T getMapper(Class<T> daoInterfaceClass) {
     return (T)Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(), new Class[]{daoInterfaceClass}, new MapperProxy(cfg.getMappers(),connection));
   //  **动态代理异常com.sun.proxy.$Proxy0 cannot be cast to**
    /**
1.第二个参数Class.getInterfaces() 主要作用是获取某类所实现的接口所有接口,返回值Class<?>[] ,这里使用就是获取接口的接口,所以出错
2.代理类没有实现接口,而是实现了某一基类。
3.当你获得代理类对象的时候,就是强制转换的哪里,如果用子类强转,也会报错,只能用接口转换
*/

    }


    @Override
    public void close() {
        if (connection!=null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

用于创建数据源的工具类DataSourceUtil

connection = DataSourceUtil.getConnection(cfg);

public class DataSourceUtil {

    /**
     * 用于获取一个连接
     * @param cfg
     * @return
     */
    public static Connection getConnection(Configuration cfg){
        try {
            Class.forName(cfg.getDriver());
            return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

继承invocationHandler接口实现方法

new MapperProxy(cfg.getMappers(),connection)

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取方法名
        String methodName = method.getName();
        //获取类名
        String name = method.getDeclaringClass().getName();
        //组合key
        String key = name + "." +methodName;
        //获取Mapper对象
        Mapper mapper = mappers.get(key);
        //判断是否有mapper
        if(mapper == null){
            throw new IllegalArgumentException("传入的参数有误");
        }
        //调用工具查询所有
        return new Executor().selectList(mapper,conn);//已略工具类
    }
}
发布了43 篇原创文章 · 获赞 2 · 访问量 998

猜你喜欢

转载自blog.csdn.net/study_azhuo/article/details/105433773