思考
什么是别名?
古代文人骚客会给自己取个好听的响亮的“别名”,如李白,字太白,号青莲居士,后世人称“诗仙”;又如你身边有人叫“穆罕默德·本·阿卜杜拉·本·阿卜杜勒·穆塔利·本·哈希姆”,估计每次喊他会让人崩溃的,所以自然而然的给他起个别名“穆罕默德”;还有作家的笔名等等,这些都是别名。别名就是为了化繁为简,便于使用和记忆。
注意事项
- 不宜有多个别名,否则会带来复杂性的提升,比如有个人有好多别名,当你们谈论时,使用不同的别名竟然不知道说的是同一个人;
- 别名冲突导致的映射错乱,比如你在大街上喊个“美女”,好多人都会响应;
实现思路
别名的本质实际是一种映射关系,所以其数据结构可以使用 Map<String, Object>,Key 不能重复正好避免别名冲突问题,存取通过 getObject(String) 便可获取别名所映射的对象。
MyBatis typeAliases
MyBatis 类型别名可为 Java 类型设置一个缩写名字,意在降低冗余的全限定类名书写。
配置方式
-
XML配置(全局配置文件)
- 单个Bean配置
<typeAliases> <typeAlias type="xx.xx.xxx.User" alias="user"/> </typeAliases>
- 包名配置
<!-- 使用包内 Bean 的首字母小写的非限定类名来作为它的别名 --> <typeAliases> <package name="xx.xx.xxx"/> </typeAliases>
- 单个Bean配置
-
注解
@Alias(“alias”)
内置别名
MyBatis 内置了一些基本常用的类型别名,在 TypeAliasRegistry 的构造器中注册,如下表所示。这里需要注意的是,内置便意味着强制使用,如使用int
,则实际类型为Integer
,而实际的int
类型需要使用_int
或_integer
。int
和Integer
的别名分别都是2个,为什么要设计为一对多?这样容易造成混乱,目前还不理解为何要这样做!
别名 | 映射的类型 |
---|---|
_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 |
除了以上这些,在 MyBatis 中还有部分内置别名,在 Configuration 的构造器中注册的,如 JDBC/MANAGED/JNDI/POOLED/UNPOOLED等,都是为了简化配置而设置的。
别名 | 映射的类型 |
---|---|
JDBC | JdbcTransactionFactory |
MANAGED | ManagedTransactionFactory |
JNDI | JndiDataSourceFactory |
POOLED | PooledDataSourceFactory |
UNPOOLED | UnpooledDataSourceFactory |
PERPETUAL | PerpetualCache |
FIFO | FifoCache |
LRU | LruCache |
SOFT | SoftCache |
WEAK | WeakCache |
DB_VENDOR | VendorDatabaseIdProvider |
XML | XMLLanguageDriver |
RAW | RawLanguageDriver |
SLF4J | Slf4jImpl |
COMMONS_LOGGING | JakartaCommonsLoggingImpl |
LOG4J | Log4jImpl |
LOG4J2 | Log4j2Impl |
JDK_LOGGING | Jdk14LoggingImpl |
STDOUT_LOGGING | StdOutImpl |
NO_LOGGING | NoLoggingImpl |
CGLIB | CglibProxyFactory |
JAVASSIST | JavassistProxyFactory |
源码细节
通过阅读源码可知:
- 类型别名注册表中的别名统一为小写,所以建议使用小写。如果别名中包含有大写字母,MyBatis 也是转换为小写进行注册和获取的。
- 别名冲突问题,如果别名已经存在注册表中,则后注册的相同别名会抛出异常
TypeException
。 - 通过包名批量注册别名需要注意,别名注册表忽略了匿名类(既然是匿名类当然没有名字,自然不能定义别名)、接口、成员类(成员类是在一个类中定义的类)。
- 通过包名批量注册别名时,默认别名为类名的全小写格式,如果存在
@Alias
注解则会使用注解定义的别名。通过<typeAlias>
标签定义别名时,忽略注解的别名。 - 通过
<typeAlias>
标签定义别名时,如果没有指定alias
属性,则默认别名为类名的全小写格式,如果存在@Alias
注解则会使用注解定义的别名。<typeAliases> <typeAlias type="xx.xx.xxx.User"/> </typeAliases>
- 别名解析规则:如果存在别名则获取实际类型,否则尝试通过类加载器加载类,可能会有类型转换异常!
总结
别名确实给项目开发提供了便捷,但是在大型项目中的别名冲突问题依然没有完美的方案,除非要求项目中不能有同名类,但是Java语言通过包边界可以定义同名的Java类。如果允许使用别名,那么项目组最好需要制定同名类别名的命名规范。如果允许自由发挥那就是灾难了,对于强迫症遇到命名就头疼!
本人愚见,如果项目不想使用别名,但由于MyBatis有内置别名,所以建议官方可以新增配置,指定是否使用别名!!