手写MyBatis框架

一、使用dom4j解析mybatis核心配置文件

1.1 配置Maven

配置dom4j、jaxen、junit的依赖

    <dependencies>
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

1.2 读取mybatis-config.xml配置文件

@Test
    public void ParseMyBatisConfigXml() throws Exception {
        //创建SAXReader对象
        SAXReader reader = new SAXReader();
        InputStream io = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");

        //得到整个xml
        Document document = reader.read(io);
        String xPath = "/configuration/environments";
        Element environments = (Element) document.selectSingleNode(xPath);
        String aDefault = environments.attributeValue("default");
        xPath = "/configuration/environments/environment[@id='"+aDefault+"']";
        Element environment = (Element) document.selectSingleNode(xPath);
        Element transactionManager = environment.element("transactionManager");

        //事务类型
        String transactionType = transactionManager.attributeValue("type");
        List<Element> dataSources = environment.element("dataSource").elements();

        //打印连接源
        dataSources.forEach(properties ->{
            String name = properties.attributeValue("name");
            String value = properties.attributeValue("value");
            System.out.println(name+"="+value);
        });

        xPath = "//mapper";
        List<Node> elements = document.selectNodes(xPath);
        elements.forEach(element -> {
            Element mapper = (Element) element;
            String resource = mapper.attributeValue("resource");
            System.out.println(resource);
        });
    }

知识点:xPath = element[@default=‘123’]表示筛选属性default为123的元素

1.3 读取CarMapper.xml文件

/**
     * 解析CarMapper.xml文件
     */
    @Test
    public void ParseSqlConfigXml() throws Exception {
        SAXReader reader = new SAXReader();
        InputStream io = ClassLoader.getSystemClassLoader().getResourceAsStream("CarMapper.xml");
        Document document = reader.read(io);

        Element mapper = document.getRootElement();

        System.out.println(mapper.attributeValue("namespace"));

        List<Element> elements = mapper.elements();
        elements.forEach(element -> {
            System.out.println(element.attributeValue("id"));
            String sql = element.getTextTrim();
            //简单正则表达式:[0-9A-Za-z_]*      表示数字+字母+下划线,数量是*个
            System.out.println(sql.replaceAll("#\\{[0-9A-Za-z_]*}","?"));
        });
    }

二、创建基础类

2.1 新建包、基础类

新建utils包,编写Resources类,写入getResourceAsReader()方法

public class Resources {
    private Resources(){};
    public static InputStream getResourceAsReader(String classPath){
        return ClassLoader.getSystemClassLoader().getResourceAsStream(classPath);
    }
}

新建core包,新建SqlSessionFactoryBuilder、SqlSessionFactory类:

public class SqlSessionFactoryBuilder {
    public SqlSessionFactoryBuilder(){};

    public SqlSessionFactory build(){
        return null;
    }
}

2.2 分析SqlSessionFactory类中需要的属性

根据学过MyBatis可以知道,一个environment对应一个数据库,一个environment对应一个SqlSessionFactory

SqlSessionFactory需要写下面信息:

  • 事务管理器
  • 数据源
  • 存放sql语句的map集合
public class SqlSessionFactory {

    /**
     * 事务管理器
     */

    /**
     * 数据源
     */

    /**
     * 存放sql语句的map集合
     * key是sqlId
     * value是对应的sql标签信息对象
     */

    Map<String,MappedStatement> mappedStatements;
}

2.3 事务管理器接口

通过配置文件,知道transaction有两种type,需要灵活切换
所以需要面向接口编程

新建Transaction接口,并编写接口

public interface Transaction {
    /**
     * 提交事务
     */
    void commit();

    /**
     * 回滚事务
     */
    void rollback();

    /**
     * 关闭事务
     */
    void close();
}

2.4 实现事务管理器接口

事务管理器有两个类型, JDBC或者MANAGED,这边只实现JDBC

public class JdbcTransaction implements Transaction{
    @Override
    public void commit() {
        connection.commit();
    }

    @Override
    public void rollback() {
        connection.rollback();
    }

    @Override
    public void close() {
        connection.close();
    }
}

可以发现,要实现JdbcTransaction就必须要有Connection,而Connection从数据源获得

2.5 实现数据源

MyBatis框架中有3个数据源类型:UNPOOLED,POOLED,JNDI
我们只实现第一个


/**
 * @author huochai
 * @date 2022/10/15 16:45
 * 不使用连接池,主要实现这个数据源
 */
public class UnPooledDataSource implements DataSource {

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

    public UnPooledDataSource(String url, String username, String password) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        this.url = url;
        this.username = username;
        this.password = password;
    }

    @Override
    public Connection getConnection() throws SQLException {
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值