mybatis 源码环境搭建

news/2025/3/16 18:59:59/文章来源:https://www.cnblogs.com/bibleghost/p/18342952

参考

从头到尾手把手教你搭建阅读Mybatis源码的环境(程序员必备技能)
Cannot enable lazy loading because Javassist is not available. Add Javassist to your classpath.

下载源码

https://github.com/mybatis/mybatis-3/

https://github.com/mybatis/parent/tree/mybatis-parent-32
https://github.com/mybatis/mybatis-3/tree/mybatis-3.5.6

新建一个maven 项目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.laolang.bzrj.mybatis</groupId><artifactId>mybatis-3-source</artifactId><version>1.0</version><packaging>pom</packaging><repositories><repository><id>public</id><name>aliyun nexus</name><url>https://maven.aliyun.com/repository/public</url><releases><enabled>true</enabled></releases></repository></repositories><pluginRepositories><pluginRepository><id>public</id><name>aliyun nexus</name><url>https://maven.aliyun.com/repository/public</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots></pluginRepository></pluginRepositories>
</project>

mybatis-parent

下载代码: https://github.com/mybatis/parent/tree/mybatis-parent-32 , 复制到项目目录,并重命名为: mybatis-parent

修改 mybatis-parent/pom.xml,主要是修改了版本号,用来和本地 mybatis 区别开来

    <groupId>org.mybatis</groupId><artifactId>mybatis-parent</artifactId><version>32-laolang</version><packaging>pom</packaging>

mybatis

下载代码: https://github.com/mybatis/mybatis-3/tree/mybatis-3.5.6 , 复制到项目目录,并重命名为: mybatis

修改 mybatis/pom.xml,主要是修改了版本号,用来和本地 mybatis 区别开来

    <parent><groupId>org.mybatis</groupId><artifactId>mybatis-parent</artifactId><version>32-laolang</version><relativePath>../mybatis-parent/pom.xml</relativePath></parent><artifactId>mybatis</artifactId><version>3.5.6-laolang</version><packaging>jar</packaging>

添加 module

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.laolang.bzrj.mybatis</groupId><artifactId>mybatis-3-source</artifactId><version>1.0</version></parent><artifactId>mybatis-source</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version><testng.version>6.14.3</testng.version><mybatis.version>3.5.6-laolang</mybatis.version><pagehelper.version>5.3.2</pagehelper.version><mysql-connector-java.version>8.0.22</mysql-connector-java.version><logback.version>1.2.12</logback.version><hutool.version>5.8.11</hutool.version><vavr.version>0.10.4</vavr.version><mapstruct.version>1.4.2.Final</mapstruct.version><guava.version>23.0</guava.version><lombok.versino>1.18.16</lombok.versino><commons-lang3.version>3.14.0</commons-lang3.version></properties><dependencies><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>${testng.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><!-- 下面这两个依赖必须添加,否则会报错: Cannot enable lazy loading because Javassist is not available. Add Javassist to your classpath.参考: https://blog.csdn.net/weixin_45056780/article/details/113449245--><dependency><groupId>ognl</groupId><artifactId>ognl</artifactId><version>3.2.15</version><scope>compile</scope><optional>true</optional></dependency><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.27.0-GA</version><scope>compile</scope><optional>true</optional></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>${pagehelper.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector-java.version}</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>${logback.version}</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool.version}</version></dependency><dependency><groupId>io.vavr</groupId><artifactId>vavr</artifactId><version>${vavr.version}</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${mapstruct.version}</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-jdk8</artifactId><version>${mapstruct.version}</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>${guava.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.versino}</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>${commons-lang3.version}</version></dependency></dependencies><build><finalName>${project.artifactId}</finalName><testResources><testResource><directory>${project.build.testSourceDirectory}</directory><excludes><exclude>**/*.java</exclude></excludes></testResource></testResources><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>${maven-compiler-plugin.version}</version><configuration><source>${maven.compiler.source}</source><target>${maven.compiler.target}</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin></plugins></build></project>

db.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_source?serverTimezone=UTC
jdbc.username=root
jdbc.password=root

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false
-->
<configuration scan="true" scanPeriod="60 seconds" debug="false"><!-- 输出到控制台 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder></appender><!-- 输出到滚动文件 --><appender name="rolling-file" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>../logs/mybatis-base/app.log</file><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern><charset>UTF-8</charset></encoder><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>../logs/mybatis-base/%d{yyyy-MM-dd}/app-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>10MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!-- 日志文件保留天数 --><maxHistory>150</maxHistory></rollingPolicy></appender><root level="DEBUG" /><logger name="org.apache.ibatis" level="DEBUG" additivity="false"><appender-ref ref="console" /><appender-ref ref="rolling-file" /></logger><logger name="com.laolang" level="DEBUG" additivity="false"><appender-ref ref="console" /><appender-ref ref="rolling-file" /></logger>
</configuration>

拦截器

package com.laolang.bzrj.mybatis.interceptor;import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class,ResultHandler.class}),@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),@Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})
})
public class MybatisPrintSqlInterceptor implements Interceptor {/*** mybatis 配置对象.*/private Configuration configuration = null;/*** 时间格式化.*/private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));/*** 拦截器主方法.** @param invocation invocation* @return sql 执行结果* @throws Throwable Throwable*/@Overridepublic Object intercept(Invocation invocation) throws Throwable {Object target = invocation.getTarget();long startTime = System.currentTimeMillis();Object result = null;try {result = invocation.proceed();return result;} finally {try {long endTime = System.currentTimeMillis();long sqlCost = endTime - startTime;StatementHandler statementHandler = (StatementHandler) target;BoundSql boundSql = statementHandler.getBoundSql();if (configuration == null) {// final DefaultParameterHandler parameterHandler = (DefaultParameterHandler) statementHandler.getParameterHandler();final ParameterHandler parameterHandler = statementHandler.getParameterHandler();// Field configurationField = ReflectionUtils.findField(//         parameterHandler.getClass(), "configuration");// ReflectionUtils.makeAccessible(configurationField);Field configurationField = ReflectUtil.getField(parameterHandler.getClass(), "configuration");ReflectUtil.setAccessible(configurationField);this.configuration = (Configuration) configurationField.get(parameterHandler);}// 输出 mapper idMetaObject metaObject = SystemMetaObject.forObject(target);MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");String id = ms.getId();// 替换参数格式化Sql语句,去除换行符String sql = formatSql(boundSql, configuration).concat(";");String warning = "";// CHECKSTYLE:OFFif (sqlCost > 2000) {warning = "[耗时过长]";}// CHECKSTYLE:ON// 开始输出 sqllog.info("map-id: {}", id);log.info("[ {} ] [ {} ] ms {}", sql, sqlCost, warning);if (result instanceof List) {log.info("Total: {}", ((List) result).size());} else {log.info("Updates: {}", result);}} catch (Exception e) {log.error("==> 打印sql 日志异常 {0}", e);}}}/*** plugin.** @param target target* @return Object*/@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}/*** setProperties.** @param properties properties*/@Overridepublic void setProperties(Properties properties) {}/*** 获取完整的sql实体的信息.** @param boundSql      boundSql* @param configuration configuration* @return 格式化后的 sql*/private String formatSql(BoundSql boundSql, Configuration configuration) {String sql = boundSql.getSql();Object parameterObject = boundSql.getParameterObject();// 输入sql字符串空判断if (StrUtil.isBlank(sql)) {return "";}if (configuration == null) {return "";}TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();sql = beautifySql(sql);List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();// 参考mybatis 源码 DefaultParameterHandlerif (parameterMappings != null) {for (ParameterMapping parameterMapping : parameterMappings) {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);}String paramValueStr = "";if (value instanceof String) {paramValueStr = "'" + value + "'";} else if (value instanceof Date) {paramValueStr = "'" + DATE_FORMAT_THREAD_LOCAL.get().format(value) + "'";} else {paramValueStr = value + "";}sql = sql.replaceFirst("\\?", paramValueStr);}}}return sql;}/*** 美化 sql.** @param sql sql* @return sql*/private String beautifySql(String sql) {sql = sql.replaceAll("[\\s\n ]+", " ");return sql;}
}

实体类

package com.laolang.bzrj.mybatis.hello;import java.time.LocalDateTime;
import lombok.Data;@Data
public class SysDictType {private Long id;private String createBy;private LocalDateTime createTime;private String updateBy;private LocalDateTime updateTime;private String remark;private String name;private String type;private String groupCode;private String status;
}

mapper

package com.laolang.bzrj.mybatis.hello;import org.apache.ibatis.annotations.Param;public interface SysDictTypeMapper {SysDictType selectById(@Param("id") Long id);
}

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.laolang.bzrj.mybatis.hello.SysDictTypeMapper"><resultMap id="SysDictTypeBaseMap" type="com.laolang.bzrj.mybatis.hello.SysDictType"><id property="id" column="id" javaType="java.lang.Long" jdbcType="BIGINT"/><result property="createBy" column="create_by" javaType="java.lang.String" jdbcType="VARCHAR"/><result property="createTime" column="create_time" javaType="java.time.LocalDateTime" jdbcType="TIMESTAMP"/><result property="updateBy" column="update_by" javaType="java.lang.String" jdbcType="VARCHAR"/><result property="updateTime" column="update_time" javaType="java.time.LocalDateTime" jdbcType="TIMESTAMP"/><result property="remark" column="remark" javaType="java.lang.String" jdbcType="VARCHAR"/><result property="name" column="name" javaType="java.lang.String" jdbcType="VARCHAR"/><result property="type" column="type" javaType="java.lang.String" jdbcType="VARCHAR"/><result property="groupCode" column="group_code" javaType="java.lang.String" jdbcType="VARCHAR"/><result property="status" column="status" javaType="java.lang.String" jdbcType="VARCHAR"/></resultMap><select id="selectById" resultMap="SysDictTypeBaseMap">select * from sys_dict_type where id = #{id}</select>
</mapper>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties" /><settings><setting name="logImpl" value="SLF4J" /></settings><plugins><plugin interceptor="com.laolang.bzrj.mybatis.interceptor.MybatisPrintSqlInterceptor" /><plugin interceptor="com.github.pagehelper.PageInterceptor" /></plugins><environments default="development"><environment id="development"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}" /><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /></dataSource></environment></environments><mappers><mapper resource="com/laolang/bzrj/mybatis/hello/SysDictTypeMapper.xml" /></mappers>
</configuration>

测试类

package com.laolang.bzrj.mybatis.hello;import cn.hutool.json.JSONUtil;
import java.io.IOException;
import java.io.Reader;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;@Slf4j
public class HelloTest {private SqlSessionFactory sqlSessionFactory;@BeforeClasspublic void beforeClass() {try (Reader reader = Resources.getResourceAsReader("com/laolang/bzrj/mybatis/hello/mybatis-config.xml")) {sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);} catch (IOException e) {throw new RuntimeException(e);}}@Testpublic void testOne() {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {SysDictTypeMapper sysDictTypeMapper = sqlSession.getMapper(SysDictTypeMapper.class);SysDictType dictType = sysDictTypeMapper.selectById(1L);log.info("dictType:{}", JSONUtil.toJsonStr(dictType));}}
}

效果

org.apache.ibatis.session.SqlSessionFactoryBuilder 49 行左右打一个断点,然后 debug 测试类

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/778079.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

05、Pod网络

4.1 Pod网络 在K8s集群中,多个节点上的Pod相互通信,要通过网络插件来完成,比如Calico网络插件。 使用kubeadm初始化K8s集群时,有指定一个参数 --pod-network-cidr=10.18.0.0/16 它是用来定义Pod的网段。 而我们在配置Calico的时候,同样也定义了一个CALICO_IPV4POOL_CIDR的…

Ros2 Moveit2 之 围绕对象进行规划 - 添加障碍物

本教程将向您介绍如何将对象插入规划场景并围绕它们进行规划。 先决条件 如果您还没有这样做,请确保您已完成RViz 中的可视化hello_moveit中的步骤。本项目假设您从上一个教程结束的地方开始。如果您只想运行本教程,您可以按照Docker 指南启动一个包含已完成教程的容器。 步骤…

使用 clearError 清除已处理的错误

title: 使用 clearError 清除已处理的错误 date: 2024/8/5 updated: 2024/8/5 author: cmdragon excerpt: 摘要:“文章介绍了clearError函数的作用与用法,用于清除已处理的错误并可实现页面重定向,提升用户体验。通过示例展示了在表单提交场景中如何应用此函数进行错误处理…

破局SAP实施难题、降低开发难度,定制化需求怎样快速上线?

前言 SAP 是全球领先的业务流程管理软件供应商之一,其提供广泛的模块化解决方案和套件,所开发的软件解决方案面向各种规模的企业,帮助客户规划和设计业务流程、分析并高效设计整个价值链,以更好的了解和响应客户需求。ERP 是企业资源规划的简称,ERP 软件涵盖所有核心业务领…

ComplatebleFuture异步调用方法,喝茶你也可以很快

ComplatebleFuture的异步用法: ComplateFuture.supplyAsync()方法会将方法体里面的方法进行异步调用,不用一直等待; ComplateFuture.allof()方法用于等待所有complatebleFutrue方法执行完毕。

若依框架导入阿里OSS报错问题解决方案

1、首先使用终端查看java JDK版本号 java -version 输出结果: java version "1.8.0_361" Java(TM) SE Runtime Environment (build 1.8.0_361-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.361-b09, mixed mode) javac-version 输出结果: javac 1.8.0_361 如…

php---空合并运算符

在做PHP开发的过程中,在引入SDK做项目开发的时候,经常会遇到一些不常见的运算符,正好自己也学习一下。运行的结果:就比如上面看到的运算符 ?: 和 ?? 运算符和我们常见的三目运算符不同,但是也有点类似。 三目运算符是这样的:$abs = !empty($list) ? a : b;而空合并运…

玄机

第一章 应急响应-webshell查杀 靶机账号密码 root xjwebshell 1.黑客webshell里面的flag flag{xxxxx-xxxx-xxxx-xxxx-xxxx} 2.黑客使用的什么工具的shell github地址的md5 flag{md5} 3.黑客隐藏shell的完整路径的md5 flag{md5} 注 : /xxx/xxx/xxx/xxx/xxx.xxx 4.黑客免杀马完整…

Spring Boot 基于 SCRAM 认证集成 Kafka 的详解

在本篇文章中,我们将探讨如何在Spring Boot应用中集成Kafka并使用SCRAM认证机制进行安全连接;并实现动态创建账号、ACL 权限、Topic,以及生产者和消费者等操作。一、说明 在现代微服务架构中,Kafka 作为消息中间件被广泛使用,而安全性则是其中的一个关键因素。在本篇文章中…

win系统下 由于管理员设置的策略,该磁盘处于脱机状态解决办法

1.运行:cmd 2.输入:DISKPART.exe 3.DISKPART> san 4.DISKPART> san policy=onlineall 5.DISKPART>list disk 6.DISKPART> select disk 1 7.DISKPART>attributes disk clear readonly 8.DISKPART>online disk

Ros2 Moveit2 之 在Riz2中可视化

本教程将向您介绍一个工具,通过在 RViz 中呈现可视化效果,该工具可以帮助您更轻松地了解 MoveIt 应用程序正在做什么。 先决条件 如果你还没有完成,请确保你已经完成了你的第一个项目hello_moveit中的步骤。这个项目假设你从上一个教程结束的地方开始。 步骤 1 添加依赖 mov…