Java-21 深入浅出 MyBatis - 手写ORM框架2 手写Resources、MappedStatment、XMLBuilder等

点一下关注吧!!!非常感谢!!持续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

目前已经更新到了:

  • MyBatis(正在更新)

框架实现

在当前的项目中,在 resources 下新建:

  • sqlMapConfig.xml
  • mapper.xml

sqlMapConfig.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://172.16.1.130:3306/wzk-mybatis?characterEncoding=utf-8"></property>
    <property name="user" value="hive"></property>
    <property name="password" value="hive@wzk.icu"></property>
    <mapper resource="mapper.xml"></mapper>
</configuration>

对应的截图如下所示:

这段代码是一个 MyBatis 的配置文件,通常命名为 mybatis-config.xml 或类似的名字。它主要完成以下任务:

  • 配置数据库连接属性,例如驱动类、JDBC URL、用户名和密码。
  • 引入 MyBatis 的映射文件,用于定义 SQL 语句和映射关系。

mapper.xml

实现一个单查询和列表的查询

xml 复制代码
<mapper namespace="icu.wzk.dao.UserInfoMapper">
    <select id="selectOne" parameterType="icu.wzk.model.UserInfo" resultType="icu.wzk.model.UserInfo">
        SELECT
            *
        FROM
            user_info
        WHERE
            username=#{username}
    </select>
    <select id="selectList" parameterType="icu.wzk.model.UserInfo" resultType="icu.wzk.model.UserInfo">
        SELECT
            *
        FROM
            user_info
    </select>
</mapper>

对应的截图如下所示:

命名空间 (namespace):

  • mapper namespace="icu.wzk.dao.UserInfoMapper":定义了映射文件的命名空间,用于标识当前的 Mapper 文件。这里的命名空间与 Java 接口类 UserInfoMapper 对应。

单条记录查询 (selectOne):

  • select id="selectOne" parameterType="icu.wzk.model.UserInfo" resultType="icu.wzk.model.UserInfo":这是一个 select 标签,用于查询单条记录。id="selectOne" 定义了方法名称,与 UserInfoMapper 接口中的方法名对应。parameterType="icu.wzk.model.UserInfo" 指定了方法的参数类型,这里是 UserInfo 对象。resultType="icu.wzk.model.UserInfo" 指定了返回结果的类型,同样是 UserInfo 对象。

实体相关

model

新建一个实体类,UserInfo

java 复制代码
package icu.wzk.model;


import lombok.Data;

@Data
public class UserInfo {

    private Long id;

    private String username;

    private String password;

    private Integer age;

}

资源相关

Configuration

java 复制代码
package icu.wzk.bean;

import lombok.Data;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


@Data
public class Configuration {

    private DataSource dataSource;

    private Map<String, MappedStatement> mappedStatementMap = new HashMap<>();

}

MappedStatment

java 复制代码
package icu.wzk.bean;


import lombok.Data;


@Data
public class MappedStatement {

    private String id;

    private String sql;

    private String parameterType;

    private String resultType;

}

Resources

java 复制代码
package icu.wzk.bean;

import java.io.InputStream;

public class Resources {

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

}

解析相关

XMLConfigerBuilder

java 复制代码
package icu.wzk.bean;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

public class XMLConfigerBuilder {
    
    private Configuration configuration;
    
    public XMLConfigerBuilder(Configuration configuration) {
        this.configuration = configuration;
    }

    public Configuration parseConfiguration(InputStream inputStream) throws DocumentException, PropertyVetoException, ClassNotFoundException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        List<Element> propertyElements = rootElement.selectNodes("//property");
        Properties properties = new Properties();
        for (Element element : propertyElements) {
            String name = element.attributeValue("name");
            String value = element.attributeValue("value");
            properties.setProperty(name, value);
        }
        ComboPooledDataSource comboSource = new ComboPooledDataSource();
        comboSource.setDriverClass(properties.getProperty("driverClass"));
        comboSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
        comboSource.setUser(properties.getProperty("user"));
        comboSource.setPassword(properties.getProperty("password"));
        configuration.setDataSource(comboSource);

        List<Element> mappedElements = rootElement.selectNodes("//mapper");
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);
        for (Element element : mappedElements) {
            String mapperPath = element.attributeValue("resource");
            InputStream resourceAsStream = Resources.getResourceAsStream(mapperPath);
            xmlMapperBuilder.parse(resourceAsStream);
        }
        return configuration;
    }
    
}

这段代码是一个用于解析 XML 配置文件的 Java 类,主要作用是读取 XML 配置文件内容,初始化应用程序所需的配置信息(例如数据库连接池配置、Mapper 文件解析等)。

类的定义

类名 XMLConfigerBuilder:表示这是一个 XML 配置解析器。

成员变量 configuration:保存应用的配置信息,类型为 Configuration。

构造方法

XMLConfigerBuilder(Configuration configuration):通过构造方法将 Configuration 对象传入并保存在成员变量中。

parseConfiguration 方法

该方法负责解析 XML 文件并初始化 Configuration 对象,主要包括以下几个步骤:

解析 XML 文档:

  • 使用 SAXReader 读取输入流(InputStream),生成 XML 文档对象。
  • 获取 XML 的根元素(rootElement)。

读取数据库配置:

  • 查找 XML 中的 节点,解析出 name 和 value 属性,将其存入 Properties 对象。
  • 创建 ComboPooledDataSource 对象,用于配置数据库连接池,设置驱动类、URL、用户名和密码等信息。
  • 将初始化好的数据源对象设置到 configuration 中。

解析 Mapper 文件

  • 查找 XML 中的 节点,提取每个节点的 resource 属性值(Mapper 文件路径)。
  • 逐个读取 Mapper 文件,通过 XMLMapperBuilder 的 parse 方法解析每个文件,将其结果更新到 configuration 中。

返回最终的 Configuration 对象

  • 方法执行完成后,返回已经完整解析并初始化的 Configuration 对象。

XMLMapperBuilder

java 复制代码
package icu.wzk.bean;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.List;

public class XMLMapperBuilder {

    private Configuration configuration;

    public XMLMapperBuilder(Configuration configuration) {
        this.configuration = configuration;
    }

    public void parse(InputStream inputStream) throws DocumentException, ClassNotFoundException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        String namespace = rootElement.attributeValue("namespace");
        List<Element> selectList = rootElement.selectNodes("select");
        for (Element element : selectList) {
            String id = element.attributeValue("id");
            String parameterType = element.attributeValue("parameterType");
            String resultType = element.attributeValue("resultType");
            String key = namespace + "." + id;
            String textTrim = element.getTextTrim();

            MappedStatement mappedStatement = new MappedStatement();
            mappedStatement.setId(id);
            mappedStatement.setParameterType(parameterType);
            mappedStatement.setResultType(resultType);
            mappedStatement.setSql(textTrim);
            configuration.getMappedStatementMap().put(key, mappedStatement);
        }
    }

}
相关推荐
sibylyue3 分钟前
Guava中常用的工具类
java·guava
奔跑吧邓邓子7 分钟前
【Java实战㉞】从0到1:Spring Boot Web开发与接口设计实战
java·spring boot·实战·web开发·接口设计
专注API从业者16 分钟前
Python/Java 代码示例:手把手教程调用 1688 API 获取商品详情实时数据
java·linux·数据库·python
奔跑吧邓邓子37 分钟前
【Java实战㉝】Spring Boot实战:从入门到自动配置的进阶之路
java·spring boot·实战·自动配置
ONLYOFFICE37 分钟前
【技术教程】如何将ONLYOFFICE文档集成到使用Spring Boot框架编写的Java Web应用程序中
java·spring boot·编辑器
叫我阿柒啊1 小时前
Java全栈开发工程师的实战面试经历:从基础到微服务
java·微服务·typescript·vue·springboot·前端开发·后端开发
雨落Liy1 小时前
SQL 函数从入门到精通:原理、类型、窗口函数与实战指南
数据库·sql
耶啵奶膘1 小时前
uni-app头像叠加显示
开发语言·javascript·uni-app
看海天一色听风起雨落1 小时前
Python学习之装饰器
开发语言·python·学习
cyforkk1 小时前
Spring 异常处理器:从混乱到有序,优雅处理所有异常
java·后端·spring·mvc