全局配置中的属性非常多,主要有如下几方面:
- properties(属性)
- settings(全局配置参数)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境集合属性对象)
- environment(环境子属性对象)
- transactionManager(事务管理)
- dataSource(数据源)
- mappers(映射器)
properties
properties 可以用来引入一个外部配置,最近常见的例子就是引入数据库的配置文件,例如我们在 resources 目录下添加一个 db.properties 文件作为数据库的配置文件,文件内容如下:
db.username=root
db.password=123
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql:///test01?serverTimezone=Asia/Shanghai
然后,利用 mybatis-config.xml
配置文件中的 properties 属性,引入这个配置文件,然后在 DataSource 中使用这个配置文件,最终配置如下:
<configuration>
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.antonio.hello.mybatis.mapper"/>
</mappers>
</configuration>
settings
Setting(设置) | Description(描述) | Valid Values(验证值组) | Default(默认值) |
cacheEnabled | 在全局范围内启用或禁用缓存配置任何映射器在此配置下 | true or false | TRUE |
lazyLoadingEnabled | 在全局范围内启用或禁用延迟加载。禁用时,所有查询将热加载 | true or false | TRUE |
aggressiveLazyLoading | 启用时,有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则,每一个属性是按需加载。 | true or false | TRUE |
multipleResultSetsEnabled | 允许或不允许从一个单独的语句(需要兼容的驱动程序)要返回多个结果集。 | true or false | TRUE |
useColumnLabel | 使用列标签,而不是列名。在这方面,不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 | true or false | TRUE |
useGeneratedKeys | 允许 JDBC 支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用,如果设置为 true,一些驱动会不兼容性,但仍然可以工作。 | true or false | FALSE |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL 只会自动映射结果没有嵌套结果映射定义里面。 FULL 会自动映射的结果映射任何复杂的(包含嵌套或其他)。 | NONE, PARTIAL, FULL | PARTIAL |
defaultExecutorType | 配置默认执行人。SIMPLE执行人确实没有什么特别的。 REUSE执行器重用准备好的语句。 BATCH执行器重用语句和批处理更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置驱动程序等待一个数据库响应的秒数。 | Any positive integer | Not Set (null) |
safeRowBoundsEnabled | 允许使用嵌套的语句RowBounds。 | true or false | FALSE |
mapUnderscoreToCamelCase | 从经典的数据库列名 A_COLUMN 启用自动映射到骆驼标识的经典的 Java 属性名 aColumn。 | true or false | FALSE |
localCacheScope | MyBatis的使用本地缓存,以防止循环引用,并加快反复嵌套查询。默认情况下(SESSION)会话期间执行的所有查询缓存。如果 localCacheScope=STATMENT 本地会话将被用于语句的执行,只是没有将数据共享之间的两个不同的调用相同的 SqlSession。 | SESSION or STATEMENT | SESSION |
dbcTypeForNull | 指定为空值时,没有特定的JDBC类型的参数的 JDBC 类型。有些驱动需要指定列的 JDBC 类型,但其他像 NULL,VARCHAR 或 OTHER 的工作与通用值。 | JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER | OTHER |
lazyLoadTriggerMethods | 指定触发延迟加载的对象的方法。 | A method name list separated by commas | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定所使用的语言默认为动态SQL生成。 | A type alias or fully qualified class name. | org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver |
callSettersOnNulls | 指定如果setter方法或地图的put方法时,将调用检索到的值是null。它是有用的,当你依靠Map.keySet()或null初始化。注意原语(如整型,布尔等)不会被设置为null。 | true or false | FALSE |
logPrefix | 指定的前缀字串,MyBatis将会增加记录器的名称。 | Any String | Not set |
logImpl | 指定MyBatis的日志实现使用。如果此设置是不存在的记录的实施将自动查找。 | SLF4J or LOG4J or LOG4J2 or JDK_LOGGING or COMMONS_LOGGING or STDOUT_LOGGING or NO_LOGGING | Not set |
proxyFactory | 指定代理工具,MyBatis将会使用创建懒加载能力的对象。 | CGLIB | JAVASSIST |
typeAliases
这个是 MyBatis 中定义的别名,分两种,一种是 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 |
本来,我们在 Mapper 中定义数据类型时,需要写全路径,如下:
<select id="getUserCount" resultType="java.lang.Integer">
select count(*) from user ;
</select>
但是,每次写全路径比较麻烦。这种时候,我们可以用类型的别名来代替,例如用 int 做 Integer 的别名:
<select id="getUserCount" resultType="int">
select count(*) from user ;
</select>
自定义别名
我们自己的对象,在 Mapper 中定义的时候,也是需要写全路径:
<select id="getAllUser" resultType="com.antonio.hello.mybatis.entity.User">
select * from user;
</select>
这种情况下,写全路径也比较麻烦,我们可以给我们自己的 User 对象取一个别名,在 mybatis-config.xml
中添加 typeAliases 节点:
<configuration>
<properties resource="db.properties"></properties>
<typeAliases>
<typeAlias type="com.antonio.hello.mybatis.entity.User" alias="user"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.antonio.hello.mybatis.mapper"/>
</mappers>
</configuration>
这里,我们给 User 对象取了一个别名叫 user,然后,我们就可以在 Mapper 中直接使用 user 来代替 User 对象了:
<select id="getAllUser" resultType="user">
select * from user;
</select>
但是,这种一个一个去枚举对象的过程非常麻烦,我们还可以批量给对象定义别名,批量定义主要是利用包扫描来做,批量定义默认的类的别名,是类名首字母小写,例如如下配置:
<typeAliases>
<package name="com.antonio.hello.mybatis.entity"/>
</typeAliases>
这个配置就表示给 com.antonio.hello.mybatis.entity
包下的所有类取别名,默认的别名就是类名首字母小写。这个时候,我们在 Mapper 中,就可以利用 user 代替 User 全路径了:
<select id="getAllUser" resultType="user">
select * from user;
</select>
在最新版中,批量定义的别名,类名首字母也可以不用小写,在实际开发中,我们一般使用第二种方式(批量定义的方式)
typeHandlers
在 MyBatis 映射中,能够自动将 Jdbc 类型映射为 Java 类型。默认的映射规则,如下:
类型处理器 | Java类型 | JDBC类型 |
BooleanTypeHandler | Boolean,boolean | 任何兼容的布尔值 |
ByteTypeHandler | Byte,byte | 任何兼容的数字或字节类型 |
ShortTypeHandler | Short,short | 任何兼容的数字或短整型 |
IntegerTypeHandler | Integer,int | 任何兼容的数字和整型 |
LongTypeHandler | Long,long | 任何兼容的数字或长整型 |
FloatTypeHandler | Float,float | 任何兼容的数字或单精度浮点型 |
DoubleTypeHandler | Double,double | 任何兼容的数字或双精度浮点型 |
BigDecimalTypeHandler | BigDecimal | 任何兼容的数字或十进制小数类型 |
StringTypeHandler | String | CHAR和VARCHAR类型 |
ClobTypeHandler | String | CLOB和LONGVARCHAR类型 |
NStringTypeHandler | String | NVARCHAR和NCHAR类型 |
NClobTypeHandler | String | NCLOB类型 |
ByteArrayTypeHandler | byte[] | 任何兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB和LONGVARBINARY类型 |
DateTypeHandler | Date(java.util) | TIMESTAMP类型 |
DateOnlyTypeHandler | Date(java.util) | DATE类型 |
TimeOnlyTypeHandler | Date(java.util) | TIME类型 |
SqlTimestampTypeHandler | Timestamp(java.sql) | TIMESTAMP类型 |
SqlDateTypeHandler | Date(java.sql) | DATE类型 |
SqlTimeTypeHandler | Time(java.sql) | TIME类型 |
ObjectTypeHandler | 任意 | 其他或未指定类型 |
EnumTypeHandler | Enumeration类型 | VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。 |
前面案例中,之所以数据能够接收成功,是因为有上面这些默认的类型处理器,处理基本数据类型,这些够用了,特殊类型,需要我们自定义类型处理器。
比如,我有一个用户爱好的字段,这个字段,在对象中,是一个 List 集合,在数据库中,是一个 VARCHAR 字段,这种情况下,就需要我们自定义类型转换器,自定义的类型转换器提供两个功能:
- 数据存储时,自动将 List 集合,转为字符串(格式自定义)
- 数据查询时,将查到的字符串再转为 List 集合
首先,在数据表中添加一个 favorites 字段。然后,在 User 对象中,添加相应的属性:
public class User {
private Integer id;
private String username;
private String address;
private List<String> favorites;
// 省略 setter/getter
}
为了能够将 List 集合中的数据存入到 VARCHAR 中,我们需要自定义一个类型转换器:
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class List2VarcharHandler implements TypeHandler<List<String>> {
public void setParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
StringBuffer sb = new StringBuffer();
for (String s : parameter) {
sb.append(s).append(",");
}
ps.setString(i, sb.toString());
}
public List<String> getResult(ResultSet rs, String columnName) throws SQLException {
String favs = rs.getString(columnName);
if (favs != null) {
return Arrays.asList(favs.split(","));
}
return null;
}
public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {
String favs = rs.getString(columnIndex);
if (favs != null) {
return Arrays.asList(favs.split(","));
}
return null;
}
public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String favs = cs.getString(columnIndex);
if (favs != null) {
return Arrays.asList(favs.split(","));
}
return null;
}
}
- 首先在这个自定义的类型转换器上添加 @MappedJdbcTypes 注解指定要处理的 Jdbc 数据类型,另外还有一个注解是 @MappedTypes 指定要处理的 Java 类型,这两个注解结合起来,就可以锁定要处理的字段是 favorites 了。
- setParameter 方法看名字就知道是设置参数的,这个设置过程由我们手动实现,我们在这里,将 List 集合中的每一项,用一个 , 串起来,组成一个字符串。
- getResult 方法,有三个重载方法,其实都是处理查询的。
接下来,修改插入的 Mapper:
<insert id="addUser" parameterType="com.antonio.hello.mybatis.entity.User">
insert into user (username,address,favorites) values (#{username},#{address},#{favorites,typeHandler=com.antonio.hello.mybatis.typehandler.List2VarcharHandler});
</insert>
然后,在 Java 代码中,调用该方法:
public class Main2 {
public static void main(String[] args) {
SqlSessionFactory instance = SqlSessionFactoryUtils.getInstance();
SqlSession sqlSession = instance.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("风气");
user.setAddress("上海");
List<String> favorites = new ArrayList<String>();
favorites.add("足球");
favorites.add("篮球");
favorites.add("乒乓球");
user.setFavorites(favorites);
mapper.addUser(user);
sqlSession.commit();
}
}
这样,List 集合存入到数据库中之后,就变成一个字符串了。读取的配置,有两个地方,一个可以在 ResultMap 中做局部配置,也可以在全局配置中进行过配置,全局配置方式如下:
<configuration>
<properties resource="db.properties"></properties>
<typeAliases>
<package name="com.antonio.hello.mybatis.entity"/>
</typeAliases>
<typeHandlers>
<package name="com.antonio.hello.mybatis.typehandler"/>
</typeHandlers>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.antonio.hello.mybatis.mapper"/>
</mappers>
</configuration>
接下来去查询,查询过程中,就会自动将字符串转为 List 集合了。
Mapper
Mapper 配置的几种方法:
<mapper resource=" " />
使用相对于类路径的资源,即 XML 的定位,从 classpath 开始写。如:
<mapper resource="mapping/User.xml" />
<mapper url="" />
使用完全限定路径,相当于使用绝对路径,这种方式使用非常少。如:
<mapper url="file:///D:\demo\xxx\User.xml" />
<mapper class=" " />
使用 mapper 接口类路径,注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。如:
<mapper class="com.antonio.hello.mybatis.mapper.UserMapper"/>
<package name=""/>
注册指定包下的所有 mapper 接口。如:
<package name="com.antonio.hello.mybatis.mapper"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。实际项目中,多采用这种方式。
更多干货请移步:https://antoniopeng.com