自定义ORM(mybatis)源码(一)-解析config.xml

自定义ORM(mybatis)源码(一)-解析config.xml

模仿mybatis

配置文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<config>
    <datasource>
        <property key="driverName" value="com.mysql.cj.jdbc.Driver"></property>
        <property key="url" value="jdbc:mysql://localhost:3306"></property>
        <property key="username" value="test"></property>
        <property key="password" value="test"></property>
    </datasource>

    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</config>

解析这个xml ,我们使用 Xpath

Resource

资源读取

java 复制代码
public class Resource {


    /**
     * 读取资源文件
     * @param path
     * @return
     */
    public static InputStream getResourceAsStream(String path) {
        System.out.println(Resource.class.getClassLoader().getSystemResource("").getPath());
        return Resource.class.getClassLoader().getResourceAsStream(path);
    }
}

XNodeParser

XPath 解析 document工具

java 复制代码
public class XNodeParser {

    private Document document;
    private XPath xPath;


    public XNodeParser(Document document) {
        this.document = document;
        this.xPath = XPathFactory.newInstance().newXPath();
    }


    /**
     *
     *   <config>
     *          <mappers>
     *             <mapper resource="mapper/UserMapper.xml"/>
     *          </mappers>
     *      </config>
     *
     * expression=/config/mappers//mapper 即获取 mappers 下面所有 mapper  node 对象节点列表
     * @param expression
     * @return
     * @throws XPathExpressionException
     */
    public NodeList getNodeList(String expression) throws XPathExpressionException {
        return (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
    }

    /**
     *    <config>
     *          <mappers>
     *             <mapper resource="mapper/UserMapper.xml"/>
     *          </mappers>
     *      </config>
     *
     * expression=/config/mappers 即获取 mappers node 对象节点
     * @param expression
     * @return
     * @throws XPathExpressionException
     */
    public Node getNodeObject(String expression) throws XPathExpressionException {
        return (Node) xPath.compile(expression).evaluate(document, XPathConstants.NODE);
    }

    /**
     * <mapper namespace="org.example.sample.dal.UserMapper">
     *  获取 namespace 值 即 org.example.sample.dal.UserMapper
     * @param node
     * @param attributeName
     * @return
     */
    public static String getAttributeValue(Node node, String attributeName) {
        return ((DeferredElementNSImpl) node).getAttribute(attributeName);
    }
}

XmlConfigParser

解析 config.xml

java 复制代码
public abstract class BaseXmlParser {

    @Getter
    protected Configuration configuration;

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


    protected Document createDocument(InputSource source) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true); // never forget this!
            DocumentBuilder documentBuilder = factory.newDocumentBuilder();
            Document xml = documentBuilder.parse(source);
            xml.getDocumentElement().normalize();
            return xml;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public abstract Configuration parse();
}


public class XmlConfigParser extends BaseXmlParser {

    private Document document;

    public XmlConfigParser(Configuration configuration, InputStream inputStream) {
        super(configuration);
        this.document = createDocument(new InputSource(inputStream));
    }


    public Configuration parse() {
        parseProperties(this.document, getConfiguration());
        return getConfiguration();
    }

    private Properties parseProperties(Document document, Configuration configuration) {
        Properties properties = new Properties();

        try {
            XNodeParser xNodeParser = new XNodeParser(document);
            //解析datasource
            extractedDataSource(xNodeParser.getNodeList("/config/datasource//property"), properties, configuration);
            //解析xml-mapper
            extractedMapper(xNodeParser.getNodeList("/config/mappers//mapper"), properties, configuration);
            System.out.println(properties);
            return properties;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private void extractedMapper(NodeList nodeList, Properties properties, Configuration configuration) {
        List<String> mapperLocation = new ArrayList<>();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node item = nodeList.item(i);
            String resource = XNodeParser.getAttributeValue(item, "resource");
            mapperLocation.add(resource);
            //解析mapper.xml
            XmlMapperParser xmlMapperParser = new XmlMapperParser(Resource.getResourceAsStream(resource), properties, configuration);
            xmlMapperParser.parse();
        }
        properties.put("mapperLocation", mapperLocation);
    }


    private void extractedDataSource(NodeList nodeList, Properties properties, Configuration configuration) throws Exception {
        BeanWrapperImpl beanWrapper = new BeanWrapperImpl(DataSourceProperties.class);
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node item = nodeList.item(i);
            String key = ((DeferredElementNSImpl) item).getAttribute("key");
            String value = ((DeferredElementNSImpl) item).getAttribute("value");
            beanWrapper.setPropertyValue(key, value);
            properties.put(key, value);
        }
        DataSourceProperties dataSourceProperties = (DataSourceProperties) beanWrapper.getWrappedInstance();
        configuration.setDataSourceFactory(new MysqlDataSourceFactory(dataSourceProperties));
    }

}

通用的 xml 解析都可以这样处理

Configuration

java 复制代码
public class Configuration {


    @Getter
    @Setter
    private DataSourceFactory dataSourceFactory;

    //Map<stmtId[namespace+sqlId],MappedStatement>
    private Map<String, MappedStatement> statements = new ConcurrentHashMap<>();

    private MapperRegistry mapperRegistry = new MapperRegistry();

    /**
     * 注册mapper
     * @param mapperClz
     */
    public void addMapper(Class<?> mapperClz) {
        mapperRegistry.addMapper(mapperClz);
    }

    /**
     * 注册 sql-map
     * @param mappedStatement
     */
    public void addMappedStatement(MappedStatement mappedStatement) {
        statements.put(mappedStatement.getFullId(), mappedStatement);
    }

    public <T> T getMapper(Class<T> mapper, SqlSession sqlSession) {
        return mapperRegistry.getMapper(mapper, sqlSession);
    }

    /**
     * 获取绑定的sql
     * mapper.namespace+id
     * @param stmtId
     * @return
     */
    public MappedStatement getMappedStatement(String stmtId){
        return statements.get(stmtId);
    }
}

good luck!

相关推荐
弗拉唐2 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
凌冰_3 小时前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
Elaine2023915 小时前
零碎04 MybatisPlus自定义模版生成代码
java·spring·mybatis
一二小选手5 小时前
【MyBatis】全局配置文件—mybatis.xml 创建xml模板
xml·java·mybatis
刘大浪6 小时前
后端数据增删改查基于Springboot+mybatis mysql 时间根据当时时间自动填充,数据库连接查询不一致,mysql数据库连接不好用
数据库·spring boot·mybatis
蓝染-惣右介8 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
武子康9 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot
一二小选手9 小时前
【Mybatis】@Param注解 resultMap手动映射
java·mybatis
郑祎亦12 小时前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis