selectByPrimaryKey源码分析(不想写了,将就看吧。。。)

114 阅读2分钟

介绍:

javax.persistence.Id 是由 JPA 定义的 annotation,记住 JPA 仅适用于关系数据的管理。

什么是JPA?

全称Java Persistence API,可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中。

了解更多:SpringBoot集成jpa 一篇就够了 超详细_springboot集成jpa切面-CSDN博客

使用位置:

@Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。 
@Id标注也可置于属性的getter方法之前。

了解更多:JPA @Id 和 @GeneratedValue 注解详解-CSDN博客

配套使用高级注解

MyBatis 3.x 版本提供了以下4个CRUD的高级注解

@SelectProvider:用于构建动态查询SQL。

@InsertProvider:用于构建动态新增SQL。

@UpdateProvider:用于构建动态更新SQL。

@DeleteProvider:用于构建动态删除SQL。

动态SQL注解主要用于编写动态SQL。这里以@SelectProvider为例,它主要包含两个注解属性,其中,type表示工具类,method表示工具类的某个方法(用于返回具体的SQL语句)。

了解更多:MyBatis使用动态SQL注解@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider_mybatis @selectprovider-CSDN博客

springbooot启动时加载BaseMapperSqlSourceBuilder的build方法

try {  
List<MappedStatement> toAddMappedStatements = new LinkedList<>();  
Object statements = configuration.getMappedStatements();  
for (Object obj : (Collection) statements) {  
if (!(obj instanceof MappedStatement)) {  
continue;  
}  
MappedStatement mappedStatement = (MappedStatement) obj;  
if (mappedStatement.getSqlSource() instanceof ProviderSqlSource) {  
Class<?> providerClass = getProviderClass(mappedStatement);  
if (providerClass != BaseMapperSqlSourceBuilder.class) {  
continue;  
}  
Class<?> mapperClass = getMapperClass(mappedStatement);  
Class<?>[] generics = getMapperGenerics(mapperClass);  
Class<?> modelClass = generics[0];  
Class<?> primaryFieldClass = generics[1];  
ResultMap resultMap = getResultMap(mappedStatement, modelClass, mapperClass);  
  
String sqlScript = getSqlScript(mappedStatement, mapperClass, modelClass, providerClass, primaryFieldClass, resultMap);  
SqlSource sqlSource = createSqlSource(mappedStatement, sqlScript);  
setSqlSource(mappedStatement, sqlSource);  
if (resultMap != null) {  
toAddMappedStatements.add(newMappedStatement(mappedStatement, resultMap));  
}  
}  
}  
for (MappedStatement mappedStatement : toAddMappedStatements) {  
replaceStatement(configuration, mappedStatement);  
}  
} catch (Exception e) {  
logger.error("初始化base mapper失败!", e);  
}  
return "sql";  
}

第一步拿到所有的mapper和xml里面的各个方法(如果是MappedStatement才循环)

image.png

第二步如果providerClass不等于BaseMapperSqlSourceBuilder也跳过循环

image.png

第三步获取到对应的mapper以及对应的model和primaryField,其实应该也就是对应到接口里面的K和T

image.png

第四步获取到一个ResultMap对象

ps:我也不知道ResultMap是撒,反正挺出名的我知道

image.png

第五步获取到了对应sql语句,初始化完成

image.png

各个小方法解析

getProviderClass方法

通过反射拿到ProviderSqlSource里面的providerTypeField字段,通过setAccessible为ture关闭安全检查,通过java.lang.reflect.Field的get()获取到字段也就是BaseMapperSqlSourceBuilder

image.png

了解更多:setAccessible(true)用法及意义-CSDN博客

Java Field get()用法及代码示例 - 纯净天空 (vimsky.com)

getMapperClass方法

通过反射Class.forName拿到mapper对象 image.png

getMapperGenerics方法

将mapper对象传入,再通过getGenericInterfaces获取该对象继承或者实现了哪些接口,getActualTypeArguments()返回表示此类型实际类型参数 总而言之就是获取那几个泛型 image.png

了解更多:Java Class getGenericInterfaces()用法及代码示例 - 纯净天空 (vimsky.com) Java之泛型ParameterizedType、getGenericSuperclass、getActualTypeArguments-CSDN博客

getResultMap

1.获取方法 2.获取返回值 3.获取泛型 image.png