四、Mybatis配置文件
1️⃣ 核心配置文件
核心配置文件mybatis-config.xml包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文件的层次结构如下(顺序不能乱):
1.properties是一个配置属性的元素 2.settings设置,mybatis最为复杂的配置也是最重要的,会改变mybatis运行时候的行为 3.typeAliases别名(在TypeAliasRegistry中可以看到mybatis提供了许多的系统别名) 4.typeHandlers 类型处理器(比如在预处理语句中设置一个参数或者从结果集中获取一个参数时候,都会用到类型处理器,在TypeHandlerRegistry中定义了很多的类型处理器) 5.objectFactory 对象工厂(myabtis在构建一个结果返回的时候,会使用一个ObjectFactory去构建pojo) 6.plugins 插件 7.environments 环境变量 environment 环境变量 transactionManager 事务管理器 dataSource 数据源 databaseIdProvider 数据库厂商标识 8.mappers 映射器
下面针对几个重要的元素environments,properties,mappers,typeAliases,settings进行讲解。
2️⃣environments(环境)
environments可以为mybatis配置多环境运行,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定),如果想切换环境修改default的值即可。
最常见的就是,生产环境和开发环境,两个环境切换必将导致数据库的切换。
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> <environment id="product"> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
数据源是必须配置的。有三种内建的数据源类型:
type="[UNPOOLED|POOLED|JNDI]") - unpooled:这个数据源的实现只是每次被请求时打开和关闭连接。 - pooled:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web 应用快速响应请求的流行处理方式。 - jndi:这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。
数据源也有很多第三方的实现,比如druid,hikari,dbcp,c3p0等等…
具体的一套环境,通过设置id进行区别,id保证唯一!
子元素节点:transactionManager - [ 事务管理器 ](以下两种事务管理器类型都不需要设置任何属性)
<!-- 语法 --> <transactionManager type="[ JDBC | MANAGED ]"/>
- 子元素节点:数据源(dataSource)
3️⃣properties(属性)
数据库连接信息我们最好放在一个单独的文件中。
🍀(1)在资源目录下新建一个db.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/ssm?useSSL=true&useUnicode=true&characterEncoding=utf8 username=root password=root
🍀(2)将db.properties文件导入核心配置文件
<configuration> <!--导入properties文件--> <properties resource="db.properties"/> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> </configuration>
4️⃣mappers(映射器)
mappers的存在就是要对写好的mapper和xml进行统一管理,要不然系统怎么知道我们写了哪些mapper。
🍀(1)常用引入方式
<mappers> <!-- 使用相对于类路径的资源引用 --> <mapper resource="com/wan/dao/userMapper.xml"/> <!-- 面向注解时使用全类名 --> <mapper class="com.wang.dao.AdminMapper"/> </mappers>
🍀(2)在Mapper文件里进行绑定
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wang.mapper.UserMapper"> </mapper>
namespace中文意思:命名空间,作用是namespace的命名必须跟某个接口同名,这才能找到实现绑定。
5️⃣typeAliases(类型别名)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
在mybatis-config.xml -> configuration进行配置:
<typeAliases> <typeAlias type="com.wang.pojo.User" alias="user"></typeAlias> <!-- 另一种方式:直接扫描一个包目录下的 --> <package name="com.wang.pojo"/> </typeAliases>
配置以后xxxMapper.xml的返回值(resultType)就可以替换为resultType user
实体类较少的时候使用第一种,较多就直接扫描包目录
第二种也可以用注解@Alias(“xxx”)给类起别名
6️⃣settings(设置)
settings能对我的一些核心功能进行配置,如懒加载、日志实现、缓存开启关闭等。
简单参数说明:
参数 | 描述 | 有效值 | 默认值 |
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关。 | true /false | true |
Enabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 | true / false | false |
useColumnLabel | 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 | true / false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。 | true / false | False |
defaultStatementTimeout | 设置超时时间,它决定驱动等待数据库响应的秒数。 | Any positive integer | Not Set (null) |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true / false | False |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | Any String | Not set |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J / LOG4J / LOG4J2 / JDK_LOGGING / COMMONS_LOGGING / STDOUT_LOGGING / NO_LOGGING | Not set |
完整的 settings 元素,有很多可以配置的选项(可以自行了解):
<settings> <!----> <setting name="cacheEnabled" value="true"/> <!----> <setting name="lazyLoadingEnabled" value="true"/> <!----> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
五、Mybatis日志配置
配置日志的一个重要原因是想在调试的时候能观察到sql语句的输出,能查看中间过程
1️⃣标准日志实现
指定 MyBatis 应该使用哪个日志记录实现。如果此设置不存在,则会自动发现日志记录实现。
STDOUT_LOGGING:标准输出日志。
<configuration> <properties resource="db.properties"/> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> ... ... <configuration>
2️⃣组合logback完成日志功能
🍀(1)导入log4j的包
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency>
🍀(2)log4j.properties配置文件
<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss} %c [%thread] %-5level %msg%n"/> <property name="log_dir" value="d:/logs" /> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <target>System.out</target> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> </appender> <appender name="file" class="ch.qos.logback.core.FileAppender"> <!--日志格式配置--> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>${pattern}</pattern> </encoder> <!--日志输出路径--> <file>${log_dir}/sql.log</file> </appender> <root level="ALL"> <appender-ref ref="console"/> </root> <logger name="mybatis.sql" level="debug" additivity="false"> <appender-ref ref="console"/> <appender-ref ref="file"/> </logger> </configuration>
🍀(3)setting设置日志实现
<settings> <setting name="logImpl" value="SLF4J"/> </settings>
六、resultMap详解
如果数据库字段和实体的字段是一一对应,那么MyBatis会【自动映射】,但是如果不一致,比如一个叫user一个叫username,那么就需要我们手动的建立一一映射的关系了。
🍀(1)Java实体类
public class User { private int id; //id private String name; //姓名,数据库为username private String password; //密码,一致 //构造 //set/get //toString() }
🍀(2)mapper接口
//根据id查询用户 User selectUserById(int id);
🍀(3)mapper映射文件
<select id="selectUserById" resultType="user"> select * from user where id = #{id} </select>
🍀(4)测试与结果分析
Test.java:
@Test public void testSelectUserById() { UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.selectUserById(1); System.out.println(user); session.close(); }
结果:
User{id=1, name='null', password='123'}
查询出来发现 name为空 . 说明出现了问题!
分析:
select * from user where id = #{id} 可以看做select id,username,password from user where id = #{id}
mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写) , 利用反射去对应的实体类中查找相应列名的set方法设值,当然找不到username
解决方案:
方案一:为列名指定别名 , 别名和java实体类的属性名一致 。
<select id="selectUserById" resultType="User"> select id , username as name ,password from user where id = #{id} </select>
方案二:使用结果集映射->ResultMap 【推荐】
<resultMap id="UserMap" type="User"> <!-- id为主键 --> <id column="id" property="id"/> <!-- column是数据库表的列名 , property是对应实体类的属性名 --> <result column="username" property="name"/> <result column="password" property="password"/> </resultMap> <select id="selectUserById" resultMap="UserMap"> select id , username , password from user where id = #{id} </select>
结论:
这个地方我们手动调整了映射关系,称之为【手动映射】。但如果不调整呢? MyBatis当然会按照约定自动映射。
当然约定的最基本的操作就是全部都一样,还有就是下划线和驼峰命名的自动转化。
<settings> <!--开启驼峰命名规则--> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>