最后
终极手撕架构师的学习笔记:分布式+微服务+开源框架+性能优化
可以看到configuration内的全部顶层节点只有9个,下面我们就一个个来分析一下
下面是一个相对完整的属性配置
上面我特意分开写,就是怕引起大家的误解,因为resource和url只允许存在一个,不能同时配置两个属性,可以看到源码中的解析过程:
同时配置了resource和url会抛出异常。
配置了properties属性之后,在xml其他配置文件中可以直接通过${xxx}来读取。
properties配置有三种方式,resource或者url指定,直接配置在子节点properties中,另一种就是上一篇提到的,直接代码中去其他地方读取properties文件,然后传入build方法。
那么这三种方式既然都能配置,假如属性配置重复了,优先级是怎么样的呢?
properties优先级
properties配置的属性如果重复,优先级如下:
-
1、第一优先:在代码中直接通过properties传入build方法。
-
2、第二优先:通过resource或者url读取到的properties文件中属性。
-
3、第三优先:直接在properties内的子标签property内定义的属性。
在实际开发中,建议是只使用一种,使用多种方式混合的话会给后期维护造成困难,而且不同类型的配置属性混合时可读性也不好。
settings是MyBatis中最复杂,也是最重要的内容之一。当然这里说的复杂并不是说配置方式复杂,而是settings能配置的东西非常多,一些很核心的功能都是通过settings标签配置的。
下面是一个完整的属性配置示例:
所有的可设置值列举如下(这些属性有个映像就可以了,不需要去记,常用的多用几次自然就记住了,不常用的需要的时候再查一下资料就可以了,所以建议大家可以收藏之后方便查询):
| 参数 | 描述 | 可选值 | 默认值 |
| — | — | — | — |
| cacheEnabled | 缓存配置的全局开关 | true
false
| true |
| lazyLoadingEnabled | 延迟加载全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 sql语句上标签的fetchType 属性来覆盖该项的开关状态。 | true
false
| false |
| aggressiveLazyLoading | 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 | true
false
| true |
| multipleResultSetsEnabled | 是否允许单一语句返回多结果集(需要兼容驱动) | true
false
| true |
| useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true
false
| true |
| useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如Derby)。 | true
false
| false |
| autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE表示取消自动映射;PARTIAL只会自动映射没有定义嵌套结果集映射的结果集。FULL会自动映射任意复杂的结果集(无论是否嵌套)。 | NONE
PARTIAL
FULL
| PARTIAL |
| defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements);BATCH 执行器将重用语句并执行批量更新。 | SIMPLE
REUSE
BATCH
| SIMPLE |
| defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数 | 有效的整数 | 默认null |
| safeRowBoundsEnabled | 允许在嵌套语句中使用分页(RowBounds) | true
false
| false |
| mapUnderscoreToCamelCase | 是否开启驼峰验证 | true
false
| false |
| localCacheScope | MyBatis 利用本地缓存机制(LocalCache)防止循环引用(circular references)和加速重复嵌套查询。默认值为SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为STATEMENT,本地会话仅用在语句执行上,对相同SqlSESSION的不同调用将不会共享数据。 | SESSION
STATEMENT
| SESSION |
| jdbcTypeForNull | 当没有为参数提供特定的 JDBC 类型时,为空值指定JDBC 类型。 某些驱动需要指定列的JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或OTHER。 | JdbcType枚举类中的所有枚举类型 | OTHER |
| lazyLoadTriggerMethods | 指定哪个对象的方法触发一次延迟加载,多个方法则用逗号隔开 | - | equals,clone,hashCode,toString |
| defaultScriptingLanguage | 指定动态SQL生成的默认语言 | 可以是类的别名也可以是全限定类名 | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
| callSettersOnNulls | 指定当结果集中值为null的时候是否调用映射对象的setter(map 对象时为 put)方法,这对于有Map.keySet()依赖或null值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成null的 | true
false
| false |
| logPrefix | 指定 MyBatis 增加到日志名称的前缀 | 任意字符串 | - |
| logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找 | SLF4J
LOG4J
LOG4J2
JDK_LOGGING
COMMONS_LOGGING
STDOUT_LOGGING
NO_LOGGING | - |
| proxyFactory | 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 | CGLIB
JAVASSIST | JAVASSIST |
类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
直接指定类名
例如:
这样配置的话在MyBatis的xml文件中可以直接使用UserMapper代替其类的全限定名。
只指定包名
也可以指定一个包名,MyBatis会在包名下面搜索需要的 Java Bean,比如:
这么配置的话每一个在指定包名中的Java类,如果没有使用注解指定名称,则会默认使用Bean的首字母小写的非限定类名来作为它的别名,如果有注解,则优先使用注解指定的别名。如:
@Alias(“lonely_wolf”)
public class LonelyWolf{
}
这里因为注解指定了别名,所以会以注解为准,如果没有注解,则默认使用lonelyWolf作为别名。
系统默认提供的别名
实际开发中,有很多返回类型是数据基本类型或者String,Map,List等非常常见的类型,这些类型MyBatis已经为我们提供好了别名,我们就不需要另外再定义了。
以下就时MyBatis中默认提供的别名:
| 别名 | 映射的类型 |
| — | — |
| _byte | byte |
| _long | long |
| _short | short |
| _int | int |
| _integer | int |
| _double | double |
| _float | float |
| _boolean | boolean |
| string | String |
| byte | Byte |
| long | Long |
| short | Short |
| int | Integer |
| integer | Integer |
| double | Double |
| float | Float |
| boolean | Boolean |
| date | Date |
| decimal | BigDecimal |
| bigdecimal | BigDecimal |
| object | Object |
| map | Map |
| hashmap | Hashmap |
| list | List |
| arraylist | Arraylist |
| collection | Collection |
| iterator | Iterator |
PS:这些别名的字母都是不区分大小写的,因为MyBatis在注册别名的时候会全部转为小写字母存储
typeHandlers主要是用来实现Java对象和数据库字段类型额转换关系。无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
配置方式如下:
MyBatis默认提供的Java Bean和数据库字段类型映射关系如下:
| 类型处理器 | Java类型 | JDBC类型 |
| — | — | — |
| BooleanTypeHandler | java.lang.Boolean,boolean | 数据库兼容的 BOOLEAN |
| ByteTypeHandler | java.lang.Byte,byte | 数据库兼容的NUMERIC或BYTE |
| ShortTypeHandler | java.lang.Short , short | 数据库兼容的 NUMERIC 或 SHORT INTEGER |
| IntegerTypeHandler | java.lang.Integer , int | 数据库兼容的 NUMERIC 或 INTEGER |
| LongTypeHandler | java.lang.Long , long | 数据库兼容的 NUMERIC 或 LONG INTEGER |
| FloatTypeHandler | java.lang.Float , float | 数据库兼容的 NUMERIC 或 FLOAT |
| DoubleTypeHandler | java.lang.Double ,double | 数据库兼容的 NUMERIC 或 DOUBLE |
| BigDecimalTypeHandler | java.math.BigDecimal | 数据库兼容的 NUMERIC 或 DECIMAL |
| StringTypeHandler | java.lang.String | CHAR , VARCHAR |
| ClobTypeHandler | java.lang.String | CLOB , LONGVARCHAR |
| NStringTypeHandler | java.lang.String | NVARCHAR , NCHAR |
| NClobTypeHandler | java.lang.String | NCLOB |
| ByteArrayTypeHandler | byte[] | 数据库兼容的字节流类型 |
| BlobTypeHandler | byte[] | BLOB , LONGVARBINARY |
| DateTypeHandler | java.util.Date | TIMESTAMP |
| DateOnlyTypeHandler | java.util.Date | DATE |
| TimeOnlyTypeHandler | java.util.Date | TIME |
| SqlTimestampTypeHandler | java.sql.Timestamp | TIMESTAMP |
| SqlDateTypeHandler | java.sql.Date | DATE |
| SqlTimeTypeHandler | java.sql.Time | TIME |
| ObjectTypeHandler | 任意类型 | OTHER 或未指定类型 |
| EnumTypeHandler | 枚举类型 | VARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引) |
| EnumOrdinalTypeHandler | 枚举类型 | 任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称) |
自定义typeHandlers
上面是MyBatis提供的默认映射类型,可以处理大部分需求,如果我们需要有不同的需求,则可以自己定义类型,具体如何定义,在后面的文章会单独分析,在这里不展开,感兴趣的可以关注我,留意后续文章。
MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则
可以通过创建自己的对象工厂来实现
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。这里我们不详细讨论,后期会有单独文章介绍MyBatis插件
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,例如:开发、测试和生产环境需要有不同的配置;或者共享相同 Schema 的多个生产数据库, 想使用相同的 SQL 映射。许多类似的用例。
注意:尽管可以配置多个环境,每个SqlSessionFactory实例只能选择其一。所以,如果想连接两个数据库,就需要创建两个SqlSessionFactory实例,每个数据库对应一个。
配置示例如下:
最后
现在其实从大厂招聘需求可见,在招聘要求上有高并发经验优先,包括很多朋友之前都是做传统行业或者外包项目,一直在小公司,技术搞的比较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。
所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。
t=“development”>
最后
现在其实从大厂招聘需求可见,在招聘要求上有高并发经验优先,包括很多朋友之前都是做传统行业或者外包项目,一直在小公司,技术搞的比较简单,没有怎么搞过分布式系统,但是现在互联网公司一般都是做分布式系统。
所以说,如果你想进大厂,想脱离传统行业,这些技术知识都是你必备的,下面自己手打了一份Java并发体系思维导图,希望对你有所帮助。
[外链图片转存中…(img-6Afuuf1x-1715479970323)]