目录
1、映射配置文件
MyBatis的映射配置文件中包含如下的配置信息;并且各个配置信息的顺序严格按照下图设置。
1.1 properties
属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:
图中有三种方式可以加载属性配置值;这三种方式的优先级为:3 》 1 》 2
1.2 settings
参数 | 描述 | 有效值 | 默认值 |
cacheEnabled | 该配置影响的所有映射器中配置的缓存的全局开关。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。 | true | false | false |
aggressiveLazyLoading | 当启用时,带有延迟加载属性的对象的加载与否完全取决于对任意延迟属性的调用;反之,每种属性将会按需加载。 | true | false | true |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 | true | false | false |
1.3 typeAliases
类型别名是为 Java 类型命名的一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
在配置文件中的定义如:
在Mapper文件中引用:
1.4 typeHandlers
类型处理器:当 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,或是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。Mybatis提供了很多默认类型处理器,一般情况下都可以满足日常的使用,不需要自定义处理器。
1.5 plugins
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
后面章节将使用分页插件。
1.5 environments
Mybatis允许配置多个环境,比如开发环境、测试环境、生产环境,但是在构建SqlSessionFactory时只能选择一个;也即每个数据库对应一个 SqlSessionFactory 实例。虽然这种方式也可以做到很方便的分离多个环境,但是在实际中一般都更多的使用Spring来管理数据源,做环境的分离。
在配置文件中可以定义多个环境,但是只能指定一个默认的:
1.6 mappers
MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。这些语句根据业务功能放置在相应的映射文件(Mapper.xml)中,所以要告诉 MyBatis 到哪里去找映射文件。MyBatis提供了四种引入方式:类路径的资源引用,完全限定资源定位符(包括 file:/// 的 URL),接口名和包名。
1 )类路径的资源
2) 完全限定资源定位符(文件绝对路径)
3)接口名(指定接口的全限定名;此种方式将在接口所在的包下查找和接口名称完全一样的mapper映射文件)
【注意】class里面的是接口的全限定名,不是包名
【缺点】Java代码和配置文件混合在一起,不利于维护
4) 包名(直接指定接口所在的包;不需要像第三种方式一样一个一个指定。)
【注意】name里面的值是接口所在的包名
【思考】①能否将java代码和xml配置分离?②能否不指定具体Mapper文件,而可以扫描指定路径?答案是:可以的,在整合spring后即可做到。
2、映射Mapper文件
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
Mapper映射文件是在实际开发过程中使用最多的,也是学习的重点。它里面包含的配置元素有如下:
cache – 给定命名空间的缓存配置。 cache-ref – 其他命名空间缓存配置的引用。 resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。 sql – 可被其他语句引用的可重用语句块。 insert – 映射插入语句 update – 映射更新语句 delete – 映射删除语句 select – 映射查询语句 |
2.1 CRUD
2.1.1 select
这个语句被称作 queryUserById,接受一个 long(或 Long)类型的参数,并返回一个 User 类型的对象。(查询结果中的列将自动映射到User对象中的属性,如果字段名称和属性名不同的则可以通过重命名字段、符合驼峰规则的可以使用驼峰规则映射、或者使用resultMap。)
参数符号 #{id} ,告诉 MyBatis 创建一个预处理语句参数,通过 JDBC,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:
【注意】当查询的参数只有一个时候,参数符号 名字可以随意起;如果超过1个则需要指定具体的参数对应。
select元素中几个常用属性:
属性名 | 描述 |
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。必选 |
parameterType | 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 |
resultType | 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。 |
resultMap | 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。 |
2.1.2 Insert
insert共享大部分select的属性;下面几个是insert和update独有:
属性名 | 描述 |
useGeneratedKeys | (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
2.1.3 update
update属性与insert一样。
2.1.4 delete
2.1.5 parameterType传入多个参数
在前面的示例中,查询的语句中都只有一个简单类型的传入参数;如果有多个查询条件,需要传入多个参数时,可以使用注解注入简单类型参数并指定名称、利用对象传递多个对象属性值给参数、使用Map传递多个参数;这三种方法。
2.1.5 .1 注解传入方式
1) 定义接口类UserMapper
Param注解:将对应形参的值在mapper.xml中传入参数时,指定传入参数的名称。
2) 编写UserMapper.xml映射文件
红色框住部分,可以使用#{account}和#{password}是因为在接口中指定了传入参数的名称。
如果不指定参数名称的话:可以使用0,1... 或者 param1,param2...
如果指定参数名称的话:可以使用指定的参数名称 或者 param1,param2...
2) 测试
2.1.5.2 POJO对象传入方式
1)UserMapper接口中的方法
2)UserMapper.xml映射文件中对应的sql语句
3)测试
如果在使用POJO对象作为传入参数的同时也想给POJO对象定义参数名称的话,也是一样可以的;那么代码就会变成下面的样子:
1)UserMapper接口中的方法
2)UserMapper.xml映射文件中对应的sql语句
3)测试
2.1.5.3 Map传入方式
1)UserMapper接口中的方法
2)UserMapper.xml映射文件中的sql
3)测试
如果想对传入的map也起参数名称;也是可以的,用法和POJO中时的一样。
2.1.6 resultType输出结果
输出类型有三种:简单类型:string、long、integer等,Pojo类型:User等,HashMap类型。
当输出结果类型为map时,则将查询的所有的字段名称作为map的key,字段对应的值为map的value值。
以输出类型为map为例:
1)UserMapper接口的方法
2)UserMapper.xml映射文件中的sql
3)测试
2.2 resultMap
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以解决如下两大问题:
- POJO属性名和表结构字段名不一致的问题(有些情况下也不是标准的驼峰格式)
- 完成高级查询,比如说,一对一、一对多、多对多。
2.2.1 自动映射
表字段名和属性名一致的时候,是否会自动映射相应值到属性中?
这个取决于resultMap的autoMapping属性,默认为true(如果在resultMap中使用了非延迟加载的关联查询元素则默认为false)。
当该属性值为true:resultmap中定义不全的属性会自动映射到user实体中(能映射的话);
当该属性值为false:只针对定义在resultMap定义的属性做映射。
resultMap里面的id和result元素都映射一个单独列的值到简单数据类型(字符 串,整型,双精度浮点数,日期等)的单独属性或字段;这两者之间的唯一不同是 id 表示的结果将是当比较对象实例时用到的标识属性。Id元素的指定有助于整体表现,一般在resultMap里面都加上。
2.2.2 解决属性与字段不一致
当查询后的返回结果映射比较复杂时候,可以在select中指定resultMap,然后在resultMap中指定比较特殊的字段对应的属性名。
2.3 通用查询
2.3.1 动态表名称
有时在项目中在查询具体的数据时,只有在程序执行过程中才知道数据表名称;比如在处理临时表的时候。这时需要将表名传入到Mapper映射文件中去根据表名查询,在MyBatis中可以如下操作:
1)定义DynamicMapper接口
2) 编写DynamicMapper.xml映射文件
【注意】此处使用的是${}参数占位符,而非#{}。
关于${}符号:
${}获取参数名称对应的值,然后直接拼接在sql语句中。在mapper中${}获取参数名称对应的值时:
① 如果在接口的方法中没有使用注解指定参数名称;如果是单个参数默认的取值为${value},如果是多于1个参数则默认的取值为${param1},${param2}...
②可以通过Param注解在接口方法中的参数前指定参数名称。
3) 测试
2.3.2 #{}与${}区别
#{} 实现的是sql语句的预处理参数,之后执行sql中用?号代替,使用时不需要关注数据类型,Mybatis自动实现数据类型的转换。并且可以防止SQL注入。
${} 实现是sql语句的直接拼接,不做数据类型转换,需要自行判断数据类型。不能防止SQL注入。
总的来说:#{}用于预执行语句的占位符;${}用于sql语句的拼接。
原则:能使用#{}的不使用${}
1.4 sql片段
在项目代码中,如果遇到有些代码是可共用的,一般会进行抽取。MyBatis的mapper映射文件中也有类似概念。可以将相同的sql语句抽取出来,然后在需要用到的地方引入即可。
在Mybatis中使用<sql id=”” />标签定义SQL片段,在需要的地方通过<include refid=“”/>引用,例如:
<!-- 定义sql片段 --> <sql id="userColumns">id,account, password, user_name, gender, age, birthday, create_time</sql> <select id="queryUserById" resultMap="userResultMap"> select <include refid="userColumns"/> from t_user where id = #{id} </select> |
这些定义的sql片段还可以跨越命名空间,在不同的mapper.xml文件中使用;用法:命名空间.sql片段的id。例如:
在引入时指定命名空间即可:
3、动态SQL
MyBatis 的强大特性之一便是它的动态 SQL 能力。当有多条件查询或操作时SQL语句的拼接是比较麻烦的事情并且拼接的时候要确保不能忘了必要的空格,逗号或者关键字。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中。
动态 SQL 元素和使用 JSTL 或其他相似的基于 XML 的文本处理器相似。MyBatis 采用功能强大的基于 OGNL 的表达式。
动态SQL元素有:
- if
- choose,when,otherwise
- where,set
- foreach
3.1 IF
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。当某些条件是可能存在或者不存在的情况下;可以使用if。
【需求】
查询男性用户;如果用户名不为空的话则再根据用户名查询。
【实现】
1)接口中方法:
2)mapper.xml映射文件中对应的SQL:
3)测试:
3.2 choose,when, otherwise
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
【需求】
根据性别查询用户:如果是男,则需要再查询年龄大于等于15岁的;如果是女,则需要再查询年龄大于等于14岁的。
【实现】
1)接口中方法:
2)mapper.xml映射文件中对应的SQL:
3)测试:
3.3 where, set
当在进行条件查询或者是在更新时,当所有的条件不是固定的情况下,在对应的关键字不是确定时;类似的情形就是:有3个查询条件进行查询,这3个查询条件有0-3个成立的机会,也就是说可能没有一个查询条件;这时,对应SQL语句而言该如何处理WHERE关键字?这就是动态SQL中where或set发挥作用的时候。
【需求】
① 根据用户名和性别查询用户;当性别的值不是1或者0时,设置查询的性别的值为-1。
② 使用set更新用户信息。
【实现】
1)接口中方法:
2)mapper.xml映射文件中对应的SQL:
3)测试:
3.4 foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
【需求】
根据用户的ID集合查询用户列表。
【实现】
1)接口中方法:
2)
2)mapper.xml映射文件中对应的SQL:
3)测试: