皮皮网

皮皮网

【源码笔记排行】【分站php源码】【交付源码混淆】mybatis 源码下载

时间:2024-11-20 23:19:49 分类:焦点

1.Mybatis 码下TypeHandler(类型处理器)转换参数到SQL和转换SQL查询结果到Java类
2.MyBatis-Plus代码生成器(3.5.1版本)
3.MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间
4.阿里技术官架构使用总结:Spring源码+MyBatis源码+Tomcat架构解析等
5.MyBatis自定义TypeHandler

mybatis 源码下载

Mybatis TypeHandler(类型处理器)转换参数到SQL和转换SQL查询结果到Java类

       TypeHandler在Mybatis中的作用

       在预处理语句(PreparedStatement)中设置参数或从结果集中取出值时,TypeHandler负责将获取的码下值以合适的方式设置到PreparedStatement,或转换成Java类型。码下通过重写TypeHandler或创建自己的码下TypeHandler,可以处理不支持的码下或非标准类型。

       在项目中,码下源码笔记排行对于只有有限个值的码下字段,常使用数字类型表示,码下如考试状态字段exam_status定义为tinyint。码下在代码中直接使用Integer表示时,码下读性和维护性较差,码下故定义枚举类来表示。码下需要实现TypeHandler以自动完成从数据库数字类型转换成枚举类的码下过程。

       实现TypeHandler的码下方案如下:定义枚举类实现EnumBase接口,包含codeOf静态方法进行数字转换。码下然后创建TypeHandler类实现org.apache.ibatis.type.TypeHandler接口,重写相应方法。避免在xml配置文件为每个枚举单独声明TypeHandler,使用Java代码动态注册,关键在于配置类。

       Mybatis注册工厂TypeHandlerRegistry初始化常见类型转换器,如String类型。执行转换时,分站php源码通过TypeHandlerRegistry获取TypeHandler。自定义枚举类能起作用,依据TypeHandlerRegistry获取TypeHandler的顺序。Mybatis使用TypeHandler实现参数设置到SQL和转换SQL查询结果到Java类的过程。

       在mapper文件中,所有parameter入参的Java参数关联TypeHandler,解析成ParameterMapping对象,其中每条SQL的parameter入参关联UnknownTypeHandler,因为字段未指定JavaType和jdbcType属性,只有指定parameterType属性,Mybatis才能获取实际Java类型。resultMap的Java参数也关联TypeHandler,通过type属性获取实际Java类型并关联TypeHandler。

       执行代码时,SQL参数设置和查询结果转换到Java类的过程由TypeHandler完成。对于参数设置,调用TypeHandler设置SQL参数,获取真正TypeHandler是通过TypeHandlerRegistry.getTypeHandler方法实现。转换查询结果到Java类的过程复杂,由DefaultResultSetHandler处理。

       了解Mybatis执行流程有助于深入理解TypeHandler的作用和实现细节。建议实际项目中实践TypeHandler的交付源码混淆使用,提高代码的可读性和可维护性。

       TypeHandler源码地址:[提供源码GitHub链接]

MyBatis-Plus代码生成器(3.5.1版本)

       MyBatis-Plus(简称 MP)是Mybatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

       特性:pom配置,依赖准备好后,创建Java类,在main()方法中:配置连接mysql数据库信息+调用自动生成API并设置各类参数,根据自定义策略,执行自动生成代码操作。这里新建一个MpGenerator.java,提供主方法main()。

       templateConfig我禁用了MP提供的模板,设置成了自己定义的。先看下MP自带的模板。

       包路径,一共支持三种引擎,Velocity对应vm后缀;Beetl对应btl后缀;Freemarker对应ftl后缀

       MP自带的模板service,controller等太简单,只是一个文件并没有提供增删改查功能,可以自己配置一个模板替换到自带的引导主页源码。就需要在templateConfig中配置一下。(自带的模板就不贴代码了,有兴趣的自己看一下)

       拿controller举例,贴一下我自己配置的。

       其实就是把增删改查的外壳设置好,把参数配置成动态的。$ 里面这些参数是哪里来的呢?接下来分析一下

       由于我用的是Velocity,看一下它的引擎源码

       一共4个方法,看名字大概分析一下,大概率是writer这个方法是主要功能,接下来断点看一下。

       模板中配置的动态参数,都是从objectMap取的。

       table数据格式,可以看到生成的entity,mapper,service,controller名称,fields取的数据库中字段信息。

       是否为主键,字段类型,名称等等。源码怎么分享可以根据这些参数来配置我们需要的模板样式。

       如果objectMap中的参数不满足我们的要求,可以自己写一个引擎继承VelocityTemplateEngine重写他的writer方法。

       我把主键的信息单独取出来了,避免每次循环调用。

       自定义配置模板文件,根据MP提供的功能,可以生成entity,mapper,mapperXML,service,serviceImpl,controller。我们可能还需要用到BO,VO等,这时候就需要自定义配置模板了。

       模板的定义跟上面说的一样。

       简单记录一下自己使用过程的学习,大家有啥想法互相学习。

       各个参数详细说明: mybatis-plus代码生成器及配置 - BlogMemory - 博客园

MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间

       Plugins

       MyBatis允许在特定点拦截映射语句执行调用。默认情况下,MyBatis允许通过插件来拦截方法调用。这些类方法的详细信息可以通过查看每个方法的签名来发现,它们的源代码存在于MyBatis发行包中。理解覆盖方法的行为至关重要,因为修改或覆盖可能会打破MyBatis的核心功能。谨慎使用插件。

       插件示例:打印每条SQL语句及其执行时间

       实现插件以打印每条真正执行的SQL语句及其执行时间。MyBatis日志可以记录SQL,但存在一些问题。编写MyBatis插件很简单,只需实现Interceptor接口。

       插件代码示例:

       注解@Intercepts和@Signature是必需的,因为Plugin的wrap方法会取用这两个注解的参数。@Intercepts中定义多个@Signature,表示符合特定条件的方法会被拦截。

       选择StatementHandler进行拦截,而不是Executor,原因是StatementHandler允许访问SQL语句和参数,而Executor更侧重于执行操作。此外,StatementHandler提供更细粒度的控制。

       使用setProperties方法配置插件属性,并通过plugin方法生成代理。代理由MyBatis的Plugin类生成,使用Proxy类确保满足方法签名的接口生成代理。

       核心是intercept方法,这里实现拦截器的主要逻辑。确保最终返回invocation.proceed(),保持拦截器的层层调用。

       配置插件的XML文件

       在config.xml中配置插件,简单明了。每个子标签代表一个插件,interceptor表示拦截器的完整路径,具体配置由个人决定。

       使用插件实例

       配置插件后,即可使用SqlCostInterceptor,这是一个通用插件。尽管CRUD不同,仍可打印完整SQL语句及其执行时间。

       插件Demo

       插件示例仅作为演示,可能无法覆盖所有场景。需要根据具体需求进行调整。即使不修改代码,插件仍能美化SQL,去除换行符。

       总结

       MyBatis插件机制强大,用于解决各种问题,如打印SQL语句、记录执行时间、实现分页或分表。编写有效拦截器的关键在于理解接口及其相关方法的功能。

阿里技术官架构使用总结:Spring源码+MyBatis源码+Tomcat架构解析等

       分享Java技术文以及学习经验也有一段时间了,实际作为程序员,我们都清楚学习的重要性,毕竟时代在发展,互联网之下,稍有落后可能就会被淘汰掉,因此我们需要不断审视自己,通过学习来提升自己。

       对于大多数程序员而言,阿里一直是目标,但进入大厂工作并非易事。今日,由阿里一线P8架构师揭秘,对其使用的技术进行总结,此PDF总结主要涉及Spring源码、MyBatis源码以及Tomcat架构解析等,以期帮助大家提升。

       如果你需要PDF版本,可直接点击下方链接免费获取。

       第一部分:Spring源码深度解析

       一、核心实现

       二、企业应用

       第二部分:MyBatis源码解析

       一、MyBatis入门

       二、配置文件解析过程

       三、映射文件解析过程

       四、SQL执行流程

       五、内置数据源

       六、缓存机制

       七、插件机制

       第三部分:Tomcat架构解析

       一、Tomcat介绍

       二、Tomcat总体架构

       三、Catalina

       四、Coyote

       五、Jasper

       六、Tomcat配置管理

       七、Web服务器集成

       八、Tomcat集群

       九、Tomcat安全

       十、Tomcat性能调优

       十一、Tomcat附加功能

       总结:

       作为Java程序员,务必不断充实自己的知识储备,关于阿里等一线大厂所使用的技术,应心中有数。

       最后,提醒一句,所学知识均为己有,如果你需要这些架构技术使用总结,我愿意免费分享,有兴趣的老铁请点击下方链接免费领取。若支持我这篇文章,不妨点赞+喜欢+收藏一键三连,谢谢!

MyBatis自定义TypeHandler

       MyBatis自定义TypeHandler1什么是TypeHandler

       TypeHandler根据字面意思即为类型处理器

       引用官方文档的描述:MyBatis在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时,都会用类型处理器将获取到的值以合适的方式转换成Java类型

       MyBatis存在一些默认的类型处理器,可参考官方文档

2为什么要使用TypeHandler

       在开发过程中,当默认的TypeHandler无法满足需求时,例如遇到MyBatis不支持的数据类型或需要特殊处理的类型转换,便需要自己定制对应的TypeHandler

       笔者会在下面的代码实现中完成如下几种情况的TypeHandler:

       逗号分隔保存在数据库中的数据,在对应的Java类中为数组

       自定义枚举

3如何自定义TypeHandler

       MyBatis提供了接口org.apache.ibatis.type.TypeHandler和类org.apache.ibatis.type.BaseTypeHandler

       官方文档给出的示例为继承BaseTypeHandler,笔者在这里也使用这种方式

       先来观察一下官方的StringTypeHandler:

publicclassStringTypeHandlerextendsBaseTypeHandler<String>{ @OverridepublicvoidsetNonNullParameter(PreparedStatementps,inti,Stringparameter,JdbcTypejdbcType)throwsSQLException{ ps.setString(i,parameter);}@OverridepublicStringgetNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{ returnrs.getString(columnName);}@OverridepublicStringgetNullableResult(ResultSetrs,intcolumnIndex)throwsSQLException{ returnrs.getString(columnIndex);}@OverridepublicStringgetNullableResult(CallableStatementcs,intcolumnIndex)throwsSQLException{ returncs.getString(columnIndex);}}

       方法名称和代码都简洁明了,观察可知,只需要完成四个方法的覆盖,即可实现自定义TypeHandler

3.1逗号分隔字符串转数组

       假设用户表t_user设计如下:

idusernametags1adminadmin,user

       对应的Java类为:

@Data@NoArgsConstructor@SuperBuilder(toBuilder=true)publicclassUser{ privateStringid;privateStringusername;privateString[]tags;}

       tags属性在数据库中用逗号分隔的字符串保存,但User类对应的属性为String数组

       可以创建StringArrayTypeHandler来解决类型转换的问题:

publicclassStringArrayTypeHandlerextendsBaseTypeHandler<String[]>{ @OverridepublicvoidsetNonNullParameter(PreparedStatementpreparedStatement,inti,String[]strings,JdbcTypejdbcType)throwsSQLException{ preparedStatement.setString(i,StringUtils.join(strings,","));}@OverridepublicString[]getNullableResult(ResultSetresultSet,Strings)throwsSQLException{ returnconvert(resultSet.getString(s));}@OverridepublicString[]getNullableResult(ResultSetresultSet,inti)throwsSQLException{ returnconvert(resultSet.getString(i));}@OverridepublicString[]getNullableResult(CallableStatementcallableStatement,inti)throwsSQLException{ returnconvert(callableStatement.getString(i));}/***将查询值转换为数组**@paramvalue查询值,String*@return转换结果,String[]*/privateString[]convert(Stringvalue){ returnStringUtils.isEmpty(value)?newString[0]:value.split(",");}}3.2自定义枚举

       如何创建包含中文名称的枚举,可以参考MyBatis中使用Java类与枚举

       先创建工具类用于根据code获取枚举实体:

publicclassValueNameEnumUtils{ privateValueNameEnumUtils(){ }publicstatic<EextendsValueNameEnum>EvalueOf(Class<E>enumClass,intvalue){ E[]enumConstants=enumClass.getEnumConstants();for(Ee:enumConstants){ if(e.getValue()==value){ returne;}}returnnull;}}

       和3.1中的情况不同,枚举的具体类型是不确定,所以我们要使用泛型的方式处理TypeHandler

       创建ValueNameEnumTypeHandler:

publicclassValueNameEnumTypeHandler<EextendsValueNameEnum>extendsBaseTypeHandler<ValueNameEnum>{ privatefinalClass<E>type;publicValueNameEnumTypeHandler(Class<E>type){ if(type==null){ thrownewIllegalArgumentException("Typeargumentcannotbenull");}this.type=type;}}

       泛型虽然名之为泛,但在编译过程中实际会发生类型擦除

       总之,对于泛型TypeHandler,我们需要声明一个用来标识具体类型的属性privatefinalClass<E>type和创建对应的构造函数publicValueNameEnumTypeHandler(Class<E>type)

       接下来和3.1中的一致,重写四个方法:

publicclassValueNameEnumTypeHandler<EextendsValueNameEnum>extendsBaseTypeHandler<ValueNameEnum>{ privatefinalClass<E>type;publicValueNameEnumTypeHandler(Class<E>type){ if(type==null){ thrownewIllegalArgumentException("Typeargumentcannotbenull");}this.type=type;}@OverridepublicvoidsetNonNullParameter(PreparedStatementps,inti,ValueNameEnumparameter,JdbcTypejdbcType)throwsSQLException{ ps.setInt(i,parameter.getValue());}@OverridepublicEgetNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{ intcode=rs.getInt(columnName);returnrs.wasNull()?null:valueOf(code);}@OverridepublicEgetNullableResult(ResultSetrs,intcolumnIndex)throwsSQLException{ intcode=rs.getInt(columnIndex);returnrs.wasNull()?null:valueOf(code);}@OverridepublicEgetNullableResult(CallableStatementcs,intcolumnIndex)throwsSQLException{ intcode=cs.getInt(columnIndex);returncs.wasNull()?null:valueOf(code);}/***根据枚举值返回枚举示例**@paramcode枚举值*@return枚举实例*/privateEvalueOf(intcode){ try{ returnValueNameEnumUtils.valueOf(type,code);}catch(Exceptionex){ thrownewIllegalArgumentException("Cannotconvert"+code+"to"+type.getSimpleName()+"bycodevalue.",ex);}}}

       完成上述代码直接启动,会抛出异常:Unabletofindausableconstructorforclasscn.houtaroy.springboot.common.MyBatis.handler.ValueNameEnumTypeHandler

       产生异常的源码如下:

public<T>TypeHandler<T>getInstance(Class<?>javaTypeClass,Class<?>typeHandlerClass){ //未指定JavaType,此处为falseif(javaTypeClass!=null){ try{ Constructor<?>c=typeHandlerClass.getConstructor(Class.class);return(TypeHandler<T>)c.newInstance(javaTypeClass);}catch(NoSuchMethodExceptionignored){ //ignored}catch(Exceptione){ thrownewTypeException("Failedinvokingconstructorforhandler"+typeHandlerClass,e);}}try{ //此处抛出异常Constructor<?>c=typeHandlerClass.getConstructor();return(TypeHandler<T>)c.newInstance();}catch(Exceptione){ thrownewTypeException("Unabletofindausableconstructorfor"+typeHandlerClass,e);}}

       报错的原因直白,没有找到ValueNameEnumTypeHandler的构造函数

       首先我们要了解下Java类构造函数的机制:如果定义了构造函数,则使用定义,否则默认生成空构造函数

       在3.1中的StringArrayTypeHandler,我们没有定义构造函数,自动生成空构造函数,typeHandlerClass.getConstructor()不会抛出异常

       但ValueNameEnumTypeHandler定义了一个构造函数ValueNameEnumTypeHandler(Class<E>type),且没有指定JavaType,typeHandlerClass.getConstructor()自然抛出异常

       解决方法有两种:

       创造空的构造函数

       指定JavaType

       笔者推荐第二种,因为第一种方式枚举类属性type会产生NPE(空指针异常),MyBatis官方也我们提供了注解@MappedTypes用于指定JavaType:

@MappedTypes(ValueNameEnum.class)publicclassValueNameEnumTypeHandler<EextendsValueNameEnum>extendsBaseTypeHandler<ValueNameEnum>{ //...}4如何使用TypeHandler

       在上一章节中,我们完成了编码实现自定义TypeHandler,但完成的TypeHandler还没办法进行使用,需要手动进行配置

       有两种配置方式:局部使用和全局使用

       以StringArrayTypeHandler举例:

4.1局部使用

       在ResultMap中使用:

<resultMapid="UserResultMap"type="cn.houtaroy.springboot.common.system.model.User"><idcolumn="id"property="id"/><resultcolumn="tags"property="tags"typeHandler="cn.houtaroy.springboot.extension.mybatis.handler.StringArrayTypeHandler"/></resultMap>

       在语句中使用:

updatet_usersettags=#{ tags,typeHandler=cn.houtaroy.springboot.extension.mybatis.handler.StringArrayTypeHandler}4.2全局使用

       使用配置文件指定handler包名:

@Data@NoArgsConstructor@SuperBuilder(toBuilder=true)publicclassUser{ privateStringid;privateStringusername;privateString[]tags;}0

       注意,此配置类型为String,只能配置一个包,推荐使用下面的方式

       手写配置类:

@Data@NoArgsConstructor@SuperBuilder(toBuilder=true)publicclassUser{ privateStringid;privateStringusername;privateString[]tags;}1

       StringArrayTypeHandler不适合全局配置,它会在全部JavaType为String[]的属性上使用

5拓展阅读

       MyBatis3官方文档中TypeHandler内容:mybatis–MyBatis3|配置

       网上搜索的在SpringBean声明周期中进行全局配置:Mybatis自定义全局TypeHander_chuobenggu的博客-CSDN博客