精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

建行二面:Mybatis 是如何工作的?

開發 數據庫
本文,我們通過核心源碼分析了 MyBatis, 它是一個輕量級的 ORM框架,它通過配置文件和注解將 Java 對象與數據庫記錄映射起來。

MyBatis 是一款優秀的持久層框架,它通過簡化 JDBC操作和提供靈活的 SQL映射方式,使 Java 開發人員能夠更高效地進行數據庫操作。那么,MyBatis的執行原理是什么?這篇文章我們將深入地分析。

一、MyBatis 配置解析

MyBatis 的配置文件通常包括全局配置文件(mybatis-config.xml)和映射文件(XXXMapper.xml)。全局配置文件主要用于配置數據源和其他全局性的信息,而映射文件則用于定義 SQL 語句。

1. 全局配置文件解析

全局配置文件在 MyBatis 啟動時被解析。SqlSessionFactoryBuilder 是 MyBatis 解析配置文件的入口點。它通過 build 方法接收一個 Reader 或 InputStream,然后調用 XMLConfigBuilder 來解析 XML 配置文件。

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        return build(parser.parse());
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
        ErrorContext.instance().reset();
        try {
            inputStream.close();
        } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
        }
    }
}

XMLConfigBuilder 解析配置文件并構建出 Configuration 對象,該對象包含了 MyBatis 的所有配置信息。

2. 映射文件解析

映射文件中定義了 SQL 語句,通過 XMLMapperBuilder 進行解析。每個 <mapper> 標簽對應一個 MappedStatement 對象,MappedStatement 包含了 SQL 語句、輸入輸出參數類型、結果集映射等信息。

public void parse() {
    if (!configuration.isResourceLoaded(resource)) {
        configurationElement(parser.evalNode("/mapper"));
        configuration.addLoadedResource(resource);
        bindMapperForNamespace();
    }
    parsePendingResultMaps();
    parsePendingCacheRefs();
    parsePendingStatements();
}

二、SQL 語句解析

MyBatis 支持動態 SQL,通過 <if>, <choose>, <foreach> 等標簽,可以根據不同的條件構造 SQL。動態 SQL 是 MyBatis 的一大特色,通過 SqlSource 接口實現。SqlSource 的主要實現類有 StaticSqlSource, DynamicSqlSource, RawSqlSource 等。

動態 SQL 解析

DynamicSqlSource 是處理動態 SQL 的核心類。它通過 SqlNode 樹來表示 SQL 語句的結構,SqlNode 是一個接口,常用的實現類有 IfSqlNode, ChooseSqlNode, WhereSqlNode 等。每個 SqlNode 的 apply 方法負責將節點轉換為 SQL 字符串。

public class DynamicSqlSource implements SqlSource {
    private final Configuration configuration;
    private final SqlNode rootSqlNode;

    public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
        this.configuration = configuration;
        this.rootSqlNode = rootSqlNode;
    }
    
    @Override
    public BoundSql getBoundSql(Object parameterObject) {
        DynamicContext context = new DynamicContext(configuration, parameterObject);
        rootSqlNode.apply(context);
        SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
        Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
        SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
        return sqlSource.getBoundSql(parameterObject);
    }
}

三、參數設置

在獲得最終的 SQL 語句后,MyBatis 需要將參數傳遞給 SQL 語句。ParameterHandler 接口負責這項工作,默認實現是 DefaultParameterHandler。

public class DefaultParameterHandler implements ParameterHandler {
    private final TypeHandlerRegistry typeHandlerRegistry;
    private final MappedStatement mappedStatement;
    private final Object parameterObject;
    private final BoundSql boundSql;
    private final Configuration configuration;

    public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        this.mappedStatement = mappedStatement;
        this.configuration = mappedStatement.getConfiguration();
        this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
        this.parameterObject = parameterObject;
        this.boundSql = boundSql;
    }

    @Override
    public void setParameters(PreparedStatement ps) throws SQLException {
        ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if (parameterMappings != null) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value;
                    String propertyName = parameterMapping.getProperty();
                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        value = boundSql.getAdditionalParameter(propertyName);
                    } else if (parameterObject == null) {
                        value = null;
                    } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                        value = parameterObject;
                    } else {
                        MetaObject metaObject = configuration.newMetaObject(parameterObject);
                        value = metaObject.getValue(propertyName);
                    }
                    TypeHandler typeHandler = parameterMapping.getTypeHandler();
                    JdbcType jdbcType = parameterMapping.getJdbcType();
                    if (value == null && jdbcType == null) {
                        jdbcType = configuration.getJdbcTypeForNull();
                    }
                    typeHandler.setParameter(ps, i + 1, value, jdbcType);
                }
            }
        }
    }
}

四、SQL 執行

SQL 執行是 MyBatis 的核心功能之一。Executor 接口定義了執行操作的基本方法,主要的實現類有 SimpleExecutor, ReuseExecutor, BatchExecutor。這些執行器通過 StatementHandler 執行 SQL 語句。

public class SimpleExecutor extends BaseExecutor {
    public SimpleExecutor(Configuration configuration, Transaction transaction) {
        super(configuration, transaction);
    }

    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.update(stmt);
        } finally {
            closeStatement(stmt);
        }
    }
}

五、結果處理

MyBatis 提供了強大的結果集映射功能,允許將 SQL 查詢結果映射為 Java 對象。ResultSetHandler 接口負責處理結果集,DefaultResultSetHandler 是其主要實現類。

public class DefaultResultSetHandler implements ResultSetHandler {
    private final TypeHandlerRegistry typeHandlerRegistry;
    private final ObjectFactory objectFactory;
    private final boolean useConstructorMappings;
    private final ReflectorFactory reflectorFactory;
    private final MappedStatement mappedStatement;
    private final RowBounds rowBounds;
    private final ParameterHandler parameterHandler;
    private final ResultHandler<?> resultHandler;
    private final BoundSql boundSql;

    public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql, RowBounds rowBounds) {
        this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
        this.objectFactory = mappedStatement.getConfiguration().getObjectFactory();
        this.useConstructorMappings = mappedStatement.getConfiguration().isUseConstructorMappings();
        this.reflectorFactory = mappedStatement.getConfiguration().getReflectorFactory();
        this.mappedStatement = mappedStatement;
        this.rowBounds = rowBounds;
        this.parameterHandler = parameterHandler;
        this.resultHandler = resultHandler;
        this.boundSql = boundSql;
    }

    @Override
    public List<Object> handleResultSets(Statement stmt) throws SQLException {
        final List<Object> multipleResults = new ArrayList<>();
        int resultSetCount = 0;
        ResultSetWrapper rsw = getFirstResultSet(stmt);
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();
        int resultMapCount = resultMaps.size();
        validateResultMapsCount(rsw, resultMapCount);
        while (rsw != null && resultMapCount > resultSetCount) {
            ResultMap resultMap = resultMaps.get(resultSetCount);
            handleResultSet(rsw, resultMap, multipleResults, null);
            rsw = getNextResultSet(stmt);
            cleanUpAfterHandlingResultSet();
            resultSetCount++;
        }
        return collapseSingleResultList(multipleResults);
    }
}

六、總結

本文,我們通過核心源碼分析了 MyBatis, 它是一個輕量級的 ORM框架,它通過配置文件和注解將 Java 對象與數據庫記錄映射起來,其核心在于通過 XML和注解配置 SQL語句,利用執行器執行 SQL,并通過結果集處理器將結果映射為 Java對象。

MyBatis的設計使得開發者可以專注于 SQL本身,而不必關心底層 JDBC操作的細節,了解和掌握其執行原理和設計模式,可以幫組我們在實際應用中更好地使用 MyBatis。

責任編輯:趙寧寧 來源: 猿java
相關推薦

2025-03-28 10:47:05

開發注解Java

2024-09-29 09:50:05

2024-10-29 09:42:50

2025-04-08 09:20:00

Sentinel限流微服務

2025-03-20 09:59:55

Spring@ProfileJava

2025-03-25 12:00:00

@Value?Spring開發

2024-10-10 17:17:57

2021-04-25 09:58:48

mmapJava面試

2025-03-18 08:30:00

Spring開發java

2021-03-17 15:54:32

IO零拷貝方式

2024-07-30 14:01:51

Java字節碼JVM?

2024-10-15 09:25:08

JDBCMybatis數據庫

2021-05-10 17:20:55

AIOps開發人員人工智能

2011-08-08 13:45:58

jQuery

2024-09-27 16:33:44

2024-08-30 08:59:15

2024-09-06 17:55:27

Springboot開發

2023-04-18 14:53:48

2010-08-02 16:56:03

ICMP協議

2023-04-18 15:09:50

點贊
收藏

51CTO技術棧公眾號

日韩一区二区视频| 综合自拍亚洲综合图不卡区| 国产97在线|日韩| 日韩视频在线观看免费视频| 亚洲欧洲日韩精品在线| 亚洲sss视频在线视频| 色女人综合av| 午夜精品久久久久久久99热黄桃| 国产精品美女久久久| 色阁综合伊人av| 在线免费看黄色片| jizzyou欧美16| 亚洲国产综合色| 色综合电影网| 懂色av成人一区二区三区| 石原莉奈在线亚洲二区| 欧美黄色片视频| 夫妇露脸对白88av| 美女福利一区| 日韩一区二区视频在线观看| 自拍偷拍 国产| 国产一线二线在线观看| 国产精品电影一区二区| 久久av一区二区三区亚洲| 国产又粗又长又黄| 性伦欧美刺激片在线观看| 欧美尺度大的性做爰视频| 性欧美13一14内谢| 极品尤物一区| 日韩一级免费观看| 日韩av卡一卡二| 成人性教育av免费网址| 亚洲一区二区av电影| 中国成人亚色综合网站| 国产二区视频在线观看| av亚洲精华国产精华精| 91福利入口| 国产一区二区女内射| 久久中文字幕一区二区三区| 久久久噜噜噜久噜久久| 欧美精品色哟哟| 中文字幕午夜精品一区二区三区 | 亚洲色大成网站www久久九九| 久久国产精品久久| 欧美熟女一区二区| 丁香婷婷综合五月| 成人免费视频网站入口| www.亚洲天堂.com| 国产成人精品亚洲777人妖| 成人有码视频在线播放| 亚洲一级黄色大片| 美女诱惑一区二区| 国产日韩欧美中文在线播放| 中文字幕视频一区二区| 男女视频一区二区| 国产精品视频xxxx| 国产女优在线播放| 久久国产精品99精品国产| 国产精品久久久久久久久久东京 | 狠狠久久亚洲欧美| 成人精品视频99在线观看免费| 无码人妻一区二区三区线| 久久精品人人| 国产精品极品美女粉嫩高清在线| 无码人妻丰满熟妇精品区| 久久成人在线| 国产精品免费一区二区三区都可以| 欧美成人一区二区三区四区| 久色成人在线| 国产精品爽爽爽| 一本色道久久综合精品婷婷| 精品一区二区三区的国产在线播放 | 欧美日韩五码| 欧美日韩国产a| 亚洲自拍第三页| 97久久综合精品久久久综合| 精品成人一区二区三区四区| 97人妻精品一区二区三区免 | 国产99精品视频| 国产一级精品aaaaa看| 日本福利在线观看| 国产精品欧美久久久久一区二区| 一区二区在线不卡| 日韩激情美女| 色婷婷激情一区二区三区| 在线免费视频一区| 亚洲经典视频| 国产网站欧美日韩免费精品在线观看| 人妻视频一区二区| 伊人久久大香线| 88xx成人精品| 亚洲天堂999| 成人动漫中文字幕| 翔田千里亚洲一二三区| 里番在线播放| 日本丰满少妇一区二区三区| 红桃视频一区二区三区免费| 欧美人体视频| 久久天天躁狠狠躁夜夜躁2014| 九九热国产视频| 日本在线不卡视频| 国产欧美丝袜| 日本中文字幕视频在线| 亚洲柠檬福利资源导航| 国产成人无码一二三区视频| 国产精品欧美一区二区三区不卡| 日韩精品视频免费专区在线播放 | 欧美性生活影院| 野花视频免费在线观看| 欧美精品系列| 亚洲91精品在线观看| 一卡二卡三卡在线| 99精品欧美一区二区蜜桃免费| 伊甸园精品99久久久久久| 超级白嫩亚洲国产第一| 911精品国产一区二区在线| 精品国产人妻一区二区三区| 国产精品伦理久久久久久| 欧美一性一乱一交一视频| 精品久久无码中文字幕| 国产精品色哟哟网站| 精品中文字幕av| 秋霞午夜一区二区三区视频| 国产亚洲在线播放| 亚洲天堂视频网站| 成人一级片网址| 中文字幕一区二区三区四区五区人 | 中文字幕永久在线不卡| 少妇人妻互换不带套| 粉嫩久久久久久久极品| 欧美成人午夜影院| 亚洲最大成人在线视频| 欧美激情中文字幕一区二区| 99精品视频在线看| 免费成人三级| 午夜精品久久久久久久99热浪潮| 国产内射老熟女aaaa∵| 国产精品久久久久四虎| www.99av.com| 精品福利久久久| 国产成人精品在线观看| 亚洲欧洲精品视频| 五月婷婷久久综合| 亚洲欧美日韩色| 亚洲精品激情| 国产精品一区二区三区免费观看| 婷婷色在线播放| 精品少妇一区二区三区日产乱码| 免费高清在线观看电视| 激情综合色综合久久综合| 亚洲丰满在线| 91精品一区| 久久在线观看视频| av在线亚洲天堂| 亚洲精品免费在线观看| 粗大的内捧猛烈进出视频| 午夜精品久久久久99热蜜桃导演| 91日本视频在线| 91精品国产91久久久久久青草| 91精品视频网| 欧美三级 欧美一级| 国产成都精品91一区二区三| 成人av在线播放观看| 爱爱精品视频| 欧美一区在线直播| 成人免费在线电影| 在线成人高清不卡| 久久免费视频6| 91色porny在线视频| 成人在线免费播放视频| 日韩三级在线| 91免费看蜜桃| 碰碰在线视频| 中文字幕不卡av| 99热这里只有精品在线观看| 亚洲在线中文字幕| 日韩一级视频在线观看| 蜜桃精品视频在线| 99久久久精品视频| 日本中文字幕在线一区| 国产精品福利在线观看| 国产在线更新| 日韩国产激情在线| 中文字幕av在线免费观看| 亚洲欧美一区二区久久| 91九色蝌蚪porny| 日韩精品亚洲一区| 男女激烈动态图| 午夜精品影视国产一区在线麻豆| 国产精品老女人视频| 青青草视频在线免费直播| 亚洲国产天堂久久综合网| 中文字幕乱码人妻二区三区| 一区二区三区四区不卡在线| 熟女少妇一区二区三区| 韩国精品免费视频| 国产av麻豆mag剧集| 日韩欧美伦理| 狠狠色噜噜狠狠色综合久| 久久久精品一区二区毛片免费看| 欧美日韩国产成人| 成年人视频在线看| 亚洲精品福利视频| 国产一区二区在线播放视频| 欧美日韩中文在线| 欧美人禽zoz0强交| 久久久久国产精品免费免费搜索| 性鲍视频在线观看| 日韩国产精品91| 福利视频一二区| 欧美1区免费| 亚洲日本无吗高清不卡| 色天下一区二区三区| 亚洲free嫩bbb| 国产私拍福利精品视频二区| 午夜精品久久久久久久99热| 在线观看小视频| 伊人一区二区三区久久精品| 五月婷婷伊人网| 日韩欧美国产综合一区| 一级特黄特色的免费大片视频| 欧美视频专区一二在线观看| 免费在线一区二区三区| 亚洲欧洲日韩一区二区三区| xxxx日本免费| 99久久久无码国产精品| 制服.丝袜.亚洲.中文.综合懂| 久久精品av麻豆的观看方式| 大肉大捧一进一出好爽动态图| 亚洲性人人天天夜夜摸| 丰满人妻一区二区三区53号| 久久一本综合| 亚洲日本无吗高清不卡| 欧美自拍偷拍| 日本一区二区在线| 九九久久成人| 久久精品日产第一区二区三区| 国产精品videossex| 97免费高清电视剧观看| 秋霞午夜一区二区三区视频| 5g影院天天爽成人免费下载| 99精品视频在线免费播放| 国产精品夜间视频香蕉| 麻豆精品蜜桃| 国产精品视频一区国模私拍| 亚洲成av在线| 国产精品香蕉av| 国产亚洲欧美日韩精品一区二区三区| 国产精品女人网站| 精品久久99| 91网站在线看| 日韩中文字幕视频网| av一区和二区| 国产精品网址| 麻豆av一区二区三区| 久久93精品国产91久久综合| 欧美一区二区高清在线观看| 九九综合九九| 亚洲国产欧美一区二区三区不卡| 日韩国产欧美一区二区| 一区二区视频在线免费| 亚洲女同另类| 国产免费黄色一级片| 伊人影院久久| 久久久999视频| 日本特黄久久久高潮 | 丁香婷婷综合五月| 成熟妇人a片免费看网站| 91天堂素人约啪| 国产黄色大片免费看| 亚洲欧洲三级电影| 久久精品这里只有精品| 午夜免费久久看| 久久久国产免费| 欧美一级高清大全免费观看| 亚洲经典一区二区三区| 国产丝袜高跟一区| 99青草视频在线播放视| 欧美成人亚洲成人| 久久毛片亚洲| 91网站在线免费观看| 日韩精品导航| 中文字幕制服丝袜在线| 亚洲高清毛片| 国产又大又黄又猛| 成人精品国产一区二区4080| av网站免费在线看| 亚洲精品欧美激情| 91video| 欧美一级精品大片| 噜噜噜在线观看播放视频| 久久久精品中文字幕| www.超碰在线| 成人h视频在线| 欧美成人午夜77777| 亚洲一区精彩视频| 亚洲看片一区| 成人不卡免费视频| av网站一区二区三区| frxxee中国xxx麻豆hd| 精品人伦一区二区三区蜜桃网站| 中文字幕人妻一区二区在线视频| 日韩免费看网站| av大片在线播放| 欧美亚洲日本网站| 日韩免费一级| 一本色道婷婷久久欧美| 一区二区三区国产在线| 韩国一区二区在线播放| 国产日韩在线不卡| 日韩黄色一级大片| 日韩一区二区影院| 午夜激情视频在线| 日韩免费不卡av| 精品福利一区| 成人在线观看毛片| 久久国产视频网| 欧洲美一区二区三区亚洲| 亚洲午夜三级在线| 国产www视频| 精品国产区一区二区三区在线观看| 亚洲性色av| 精品一区在线播放| 国产在线成人| 巨乳女教师的诱惑| 亚洲视频在线一区| 一级黄色片在线观看| 亚洲视频在线视频| 性感女国产在线| 国产伦精品一区二区三区在线 | 欧亚精品一区| www.好吊操| 高清在线观看日韩| 欧美精品久久久久性色| 日韩一区二区免费电影| 一区二区高清不卡| 国产精品日韩av| 欧美日韩精品一区二区三区在线观看| 男人天堂手机在线视频| 国产精品一级二级三级| 亚洲色图综合区| 日韩一区二区三区精品视频| 欧美人xxx| 亚洲综合精品一区二区| 91精品高清| 性生活一级大片| 亚洲精品videosex极品| 国产人妖在线播放| 欧美xxxx做受欧美.88| 国产在线一区不卡| 肉大捧一出免费观看网站在线播放 | 手机av免费看| 日本高清成人免费播放| 国产在线中文字幕| 国产精品欧美日韩久久| 日本欧美视频| 日韩av加勒比| 一区二区三区精品| 欧美一区二区黄片| 欧美亚洲国产日韩2020| 免费久久久久久久久| 美女网站视频黄色| 国产精品毛片a∨一区二区三区 | 亚洲电影av在线| 台湾佬中文娱乐网欧美电影| 欧美区高清在线| 六月丁香综合在线视频| 在线免费观看亚洲视频| 亚洲白拍色综合图区| 亚洲人体影院| 中文精品一区二区三区| 国产精品99久久久| 天天爽夜夜爽夜夜爽精品| 一区二区三区四区精品| www.久久久久爱免| av在线观看地址| 久久精品夜色噜噜亚洲aⅴ| 中文字幕在线观看精品| 欧美国产日韩一区二区三区| 亚洲美女15p| 日本中文字幕观看| 亚洲大片精品永久免费| 毛片免费在线播放| 亚洲一区国产精品| 亚洲欧美日韩国产| 五月天免费网站| 亚洲黄色免费三级| 欧美综合影院| 国产精品无码人妻一区二区在线 | 亚洲欧洲成视频免费观看| 色狠狠一区二区三区| 人妻久久久一区二区三区| 日本一区二区不卡视频| xxxx国产精品| 国产精品三级美女白浆呻吟| 精品动漫3d一区二区三区免费| 人妻aⅴ无码一区二区三区| 欧美一级艳片视频免费观看| 自拍视频在线看| 国产精品三级一区二区|