全局配置中的属性非常多,主要有如下几方面:
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&#61;"db.properties">properties><environments default&#61;"development"><environment id&#61;"development"><transactionManager type&#61;"JDBC"/><dataSource type&#61;"POOLED"><property name&#61;"driver" value&#61;"${db.driver}"/><property name&#61;"url" value&#61;"${db.url}"/><property name&#61;"username" value&#61;"${db.username}"/><property name&#61;"password" value&#61;"${db.password}"/>dataSource>environment>environments><mappers><package name&#61;"com.antonio.hello.mybatis.mapper"/>mappers>
configuration>
Setting(设置) | Description&#xff08;描述&#xff09; | Valid Values(验证值组) | Default(默认值) |
---|---|---|---|
cacheEnabled | 在全局范围内启用或禁用缓存配置任何映射器在此配置下 | true or false | TRUE |
lazyLoadingEnabled | 在全局范围内启用或禁用延迟加载。禁用时&#xff0c;所有查询将热加载 | true or false | TRUE |
aggressiveLazyLoading | 启用时&#xff0c;有延迟加载属性的对象将被完全加载后调用懒惰的任何属性。否则&#xff0c;每一个属性是按需加载。 | true or false | TRUE |
multipleResultSetsEnabled | 允许或不允许从一个单独的语句&#xff08;需要兼容的驱动程序&#xff09;要返回多个结果集。 | true or false | TRUE |
useColumnLabel | 使用列标签&#xff0c;而不是列名。在这方面&#xff0c;不同的驱动有不同的行为。参考驱动文档或测试两种方法来决定你的驱动程序的行为如何。 | true or false | TRUE |
useGeneratedKeys | 允许 JDBC 支持生成的密钥。兼容的驱动程序是必需的。此设置强制生成的键被使用&#xff0c;如果设置为 true&#xff0c;一些驱动会不兼容性&#xff0c;但仍然可以工作。 | true or false | FALSE |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段/属性。NONE自动映射。 PARTIAL 只会自动映射结果没有嵌套结果映射定义里面。 FULL 会自动映射的结果映射任何复杂的&#xff08;包含嵌套或其他&#xff09;。 | 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的使用本地缓存&#xff0c;以防止循环引用&#xff0c;并加快反复嵌套查询。默认情况下&#xff08;SESSION&#xff09;会话期间执行的所有查询缓存。如果 localCacheScope&#61;STATMENT 本地会话将被用于语句的执行&#xff0c;只是没有将数据共享之间的两个不同的调用相同的 SqlSession。 | SESSION or STATEMENT | SESSION |
dbcTypeForNull | 指定为空值时&#xff0c;没有特定的JDBC类型的参数的 JDBC 类型。有些驱动需要指定列的 JDBC 类型&#xff0c;但其他像 NULL&#xff0c;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方法时&#xff0c;将调用检索到的值是null。它是有用的&#xff0c;当你依靠Map.keySet&#xff08;&#xff09;或null初始化。注意原语&#xff08;如整型&#xff0c;布尔等&#xff09;不会被设置为null。 | true or false | FALSE |
logPrefix | 指定的前缀字串&#xff0c;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 | 指定代理工具&#xff0c;MyBatis将会使用创建懒加载能力的对象。 | CGLIB | JAVASSIST |
这个是 MyBatis 中定义的别名&#xff0c;分两种&#xff0c;一种是 MyBatis 自带的别名&#xff0c;另一种是我们自定义的别名。
别名 | 映射的类型 |
---|---|
_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 |
本来&#xff0c;我们在 Mapper 中定义数据类型时&#xff0c;需要写全路径&#xff0c;如下&#xff1a;
<select id&#61;"getUserCount" resultType&#61;"java.lang.Integer">select count(*) from user ;
select>
但是&#xff0c;每次写全路径比较麻烦。这种时候&#xff0c;我们可以用类型的别名来代替&#xff0c;例如用 int 做 Integer 的别名&#xff1a;
<select id&#61;"getUserCount" resultType&#61;"int">select count(*) from user ;
select>
我们自己的对象&#xff0c;在 Mapper 中定义的时候&#xff0c;也是需要写全路径&#xff1a;
<select id&#61;"getAllUser" resultType&#61;"com.antonio.hello.mybatis.entity.User">select * from user;
select>
这种情况下&#xff0c;写全路径也比较麻烦&#xff0c;我们可以给我们自己的 User 对象取一个别名&#xff0c;在 mybatis-config.xml
中添加 typeAliases 节点&#xff1a;
<configuration><properties resource&#61;"db.properties">properties><typeAliases><typeAlias type&#61;"com.antonio.hello.mybatis.entity.User" alias&#61;"user"/>typeAliases><environments default&#61;"development"><environment id&#61;"development"><transactionManager type&#61;"JDBC"/><dataSource type&#61;"POOLED"><property name&#61;"driver" value&#61;"${db.driver}"/><property name&#61;"url" value&#61;"${db.url}"/><property name&#61;"username" value&#61;"${db.username}"/><property name&#61;"password" value&#61;"${db.password}"/>dataSource>environment>environments><mappers><package name&#61;"com.antonio.hello.mybatis.mapper"/>mappers>
configuration>
这里&#xff0c;我们给 User 对象取了一个别名叫 user&#xff0c;然后&#xff0c;我们就可以在 Mapper 中直接使用 user 来代替 User 对象了&#xff1a;
<select id&#61;"getAllUser" resultType&#61;"user">select * from user;
select>
但是&#xff0c;这种一个一个去枚举对象的过程非常麻烦&#xff0c;我们还可以批量给对象定义别名&#xff0c;批量定义主要是利用包扫描来做&#xff0c;批量定义默认的类的别名&#xff0c;是类名首字母小写&#xff0c;例如如下配置&#xff1a;
<typeAliases><package name&#61;"com.antonio.hello.mybatis.entity"/>
typeAliases>
这个配置就表示给 com.antonio.hello.mybatis.entity
包下的所有类取别名&#xff0c;默认的别名就是类名首字母小写。这个时候&#xff0c;我们在 Mapper 中&#xff0c;就可以利用 user 代替 User 全路径了&#xff1a;
<select id&#61;"getAllUser" resultType&#61;"user">select * from user;
select>
在最新版中&#xff0c;批量定义的别名&#xff0c;类名首字母也可以不用小写&#xff0c;在实际开发中&#xff0c;我们一般使用第二种方式&#xff08;批量定义的方式&#xff09;
在 MyBatis 映射中&#xff0c;能够自动将 Jdbc 类型映射为 Java 类型。默认的映射规则&#xff0c;如下&#xff1a;
类型处理器 | Java类型 | JDBC类型 |
---|---|---|
BooleanTypeHandler | Boolean&#xff0c;boolean | 任何兼容的布尔值 |
ByteTypeHandler | Byte&#xff0c;byte | 任何兼容的数字或字节类型 |
ShortTypeHandler | Short&#xff0c;short | 任何兼容的数字或短整型 |
IntegerTypeHandler | Integer&#xff0c;int | 任何兼容的数字和整型 |
LongTypeHandler | Long&#xff0c;long | 任何兼容的数字或长整型 |
FloatTypeHandler | Float&#xff0c;float | 任何兼容的数字或单精度浮点型 |
DoubleTypeHandler | Double&#xff0c;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&#xff08;java.util&#xff09; | TIMESTAMP类型 |
DateOnlyTypeHandler | Date&#xff08;java.util&#xff09; | DATE类型 |
TimeOnlyTypeHandler | Date&#xff08;java.util&#xff09; | TIME类型 |
SqlTimestampTypeHandler | Timestamp&#xff08;java.sql&#xff09; | TIMESTAMP类型 |
SqlDateTypeHandler | Date&#xff08;java.sql&#xff09; | DATE类型 |
SqlTimeTypeHandler | Time&#xff08;java.sql&#xff09; | TIME类型 |
ObjectTypeHandler | 任意 | 其他或未指定类型 |
EnumTypeHandler | Enumeration类型 | VARCHAR-任何兼容的字符串类型&#xff0c;作为代码存储&#xff08;而不是索引&#xff09;。 |
前面案例中&#xff0c;之所以数据能够接收成功&#xff0c;是因为有上面这些默认的类型处理器&#xff0c;处理基本数据类型&#xff0c;这些够用了&#xff0c;特殊类型&#xff0c;需要我们自定义类型处理器。
比如&#xff0c;我有一个用户爱好的字段&#xff0c;这个字段&#xff0c;在对象中&#xff0c;是一个 List 集合&#xff0c;在数据库中&#xff0c;是一个 VARCHAR 字段&#xff0c;这种情况下&#xff0c;就需要我们自定义类型转换器&#xff0c;自定义的类型转换器提供两个功能&#xff1a;
首先&#xff0c;在数据表中添加一个 favorites 字段。然后&#xff0c;在 User 对象中&#xff0c;添加相应的属性&#xff1a;
public class User {private Integer id;private String username;private String address;private List<String> favorites;// 省略 setter/getter
}
为了能够将 List 集合中的数据存入到 VARCHAR 中&#xff0c;我们需要自定义一个类型转换器&#xff1a;
&#64;MappedJdbcTypes(JdbcType.VARCHAR)
&#64;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 &#61; 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 &#61; rs.getString(columnName);if (favs !&#61; null) {return Arrays.asList(favs.split(","));}return null;}public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {String favs &#61; rs.getString(columnIndex);if (favs !&#61; null) {return Arrays.asList(favs.split(","));}return null;}public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {String favs &#61; cs.getString(columnIndex);if (favs !&#61; null) {return Arrays.asList(favs.split(","));}return null;}
}
接下来&#xff0c;修改插入的 Mapper&#xff1a;
<insert id&#61;"addUser" parameterType&#61;"com.antonio.hello.mybatis.entity.User">insert into user (username,address,favorites) values (#{username},#{address},#{favorites,typeHandler&#61;com.antonio.hello.mybatis.typehandler.List2VarcharHandler});
insert>
然后&#xff0c;在 Java 代码中&#xff0c;调用该方法&#xff1a;
public class Main2 {public static void main(String[] args) {SqlSessionFactory instance &#61; SqlSessionFactoryUtils.getInstance();SqlSession sqlSession &#61; instance.openSession();UserMapper mapper &#61; sqlSession.getMapper(UserMapper.class);User user &#61; new User();user.setUsername("风气");user.setAddress("上海");List<String> favorites &#61; new ArrayList<String>();favorites.add("足球");favorites.add("篮球");favorites.add("乒乓球");user.setFavorites(favorites);mapper.addUser(user);sqlSession.commit();}
}
这样&#xff0c;List 集合存入到数据库中之后&#xff0c;就变成一个字符串了。读取的配置&#xff0c;有两个地方&#xff0c;一个可以在 ResultMap 中做局部配置&#xff0c;也可以在全局配置中进行过配置&#xff0c;全局配置方式如下&#xff1a;
<configuration><properties resource&#61;"db.properties">properties><typeAliases><package name&#61;"com.antonio.hello.mybatis.entity"/>typeAliases><typeHandlers><package name&#61;"com.antonio.hello.mybatis.typehandler"/>typeHandlers><environments default&#61;"development"><environment id&#61;"development"><transactionManager type&#61;"JDBC"/><dataSource type&#61;"POOLED"><property name&#61;"driver" value&#61;"${db.driver}"/><property name&#61;"url" value&#61;"${db.url}"/><property name&#61;"username" value&#61;"${db.username}"/><property name&#61;"password" value&#61;"${db.password}"/>dataSource>environment>environments><mappers><package name&#61;"com.antonio.hello.mybatis.mapper"/>mappers>
configuration>
接下来去查询&#xff0c;查询过程中&#xff0c;就会自动将字符串转为 List 集合了。
Mapper 配置的几种方法&#xff1a;
使用相对于类路径的资源&#xff0c;即 XML 的定位&#xff0c;从 classpath 开始写。如&#xff1a;
<mapper resource&#61;"mapping/User.xml" />
使用完全限定路径&#xff0c;相当于使用绝对路径&#xff0c;这种方式使用非常少。如&#xff1a;
<mapper url&#61;"file:///D:\demo\xxx\User.xml" />
使用 mapper 接口类路径&#xff0c;注意&#xff1a;此种方法要求 mapper 接口名称和 mapper 映射文件名称相同&#xff0c;且放在同一个目录中。如&#xff1a;
<mapper class&#61;"com.antonio.hello.mybatis.mapper.UserMapper"/>
注册指定包下的所有 mapper 接口。如&#xff1a;
<package name&#61;"com.antonio.hello.mybatis.mapper"/>
注意&#xff1a;此种方法要求 mapper 接口名称和 mapper 映射文件名称相同&#xff0c;且放在同一个目录中。实际项目中&#xff0c;多采用这种方式。
更多干货请移步&#xff1a;https://antoniopeng.com