前言
完成了简单的CRUD
解读了Mybatis-config.xml的标签
学会了日志工厂的使用
通过源码分析了Mybatis的运行流程
现在来看看sql语句的xml文件:Mapper.xml(映射器)
UserMapper.xml
<?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接口-->
<mapper namespace="com.learn.dao.UserMapper">
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--column是数据库字段,property是实体类的属性-->
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" resultMap="UserMap" parameterType="int">
select * from mybatis.user where id = #{id}
</select>
</mapper>
我们的UserMapper.xml由这几个要素组成:
1. 约束
<?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.xml是xml文件,第一行必须是声明,第二行是指定外部约束文件
当有了外部的约束文件,才能规定标签,我们打一个尖括号就出来的标签全是约束文件指定的
通过这个约束文件可以看到:
根标签是mapper,内部有cache-ref | cache | resultMap* | parameterMap* | sql* | insert* | update* | delete* | select
他们不像mybatis-config.xml,并没有标签顺序
不清楚xml约束的可以看:真的了解XML吗? - XML 基础
2.根标签
根标签只有一个属性namespace
这个属性指定我们这个mapper.xml对应的mapper接口
3.子标签
cache-ref | cache | resultMap* | parameterMap* | sql* | insert* | update* | delete* | select
官网的说法:
这些是具体的子标签,后面研究
怎么查看这些标签
鼠标点到mapper标签上,按住ctrl,点击鼠标左键
会有一个下划线,就可以进入mybatis-3-mapper.dtd(dtd约束)
初始项目
先搭建一个初始项目跑起来(会的话可以直接跳过,到后面的标签解析)
Mybatis连接数据库
db.properties设置连接数据库的属性
mybatis-config.xml配置mybatis
设置别名,映射和数据库连接
实体类(实体类偷懒神器:Lombok插件):
package com.learn.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}
工具类MybatisUtils(负责创建sqlSession):
UserMapper接口:定义操作数据库的方法
UserMapper.xml:sql操作数据库
测试类:
junit测试
数据库:
测试结果:
getUserById(1),即查找id=1的User
Select标签
先看这个最常用的标签
说明select内部可以有include | trim | where | set | foreach | choose | if | bind
标签
也可以直接写sql语句(#PCDATA)
有很多属性
常用的有:
- id:标识mapper接口的方法,与之相对应(我们这个select对应的就是getUserById方法)
- parameterType:传入的参数类型,Mybatis内置了一下属性别名如int类型就要写_int(默认是int型,可以省略该属性),如果是我们自己的实体类,就需要写完全的类名如
com.learn.pojo.User
,当然可以通过mybatis-config.xml设置别名
如果不清楚可以看:Mybatis - 核心配置文件Mybatis-config.xml标签详解(上)
resultType:结果类型,和parameterType要求一样
resultMap:结果集,当返回的结果需要我们处理时,可以使用它(具体的后面解析)
timeout:超时时间
databaseId:当支持多个数据库时,需要设置属性表示该sql是运行在哪个数据库
内部的标签中,include是这个标签引入外部数据
必须有refid,也就是外部数据名或者地址
可以有property子标签
//通过id查找
<include refid="sql">
<property name="id" value="1"/>
</include>
//通过地址查找,然后取出id
<include refid="com.learn.dao.UserMapper">
<property name="id" value="${id}"/>
</include>
用于复用sql语句
关于其他的内部标签,放到动态sql学习
增删改
insert、update、delete3个标签都约束都是一样的,与select类似
但是没有返回结果,因为从我们学习jdbc时候就知道,增删改resultSet都是int数据,表示本次操作改动的数据库数据条数
注意:select标签内可以使用增删改sql,但是没有返回结果,为Integer的null
这个让我碰了个大坑:Mybatis碰到的问题
sql标签
sql标签是可被重用的sql语句块
<select id="getUserById" resultMap="UserMap">
select * from mybatis.user
<include refid="sql"/>
</select>
<sql id="sql">
where id = #{id}
</sql>
sql设置一个sql语句块,需要的话就直接通过include标签拿到即可
依旧可以查到数据
ResultMap:处理别名
ResultMap是用于处理返回的结果集
上面的案例里:
数据库字段:
实体类字段:
mybatis默认是需要数据库与实体类字段对应
把前面的resultMap改成resultType
当字段不对应的时候,该实体类字段为空值
解决方法:
- 直接给字段取别名
既然pwd对应的是password,那我就把名字改成对应的就可以了(简单粗暴)
但是,如果不知道字段,就没办法用这种方法了
- resultMap结果集映射
当返回的结果集需要处理时,添加resultMap标签处理
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--column是数据库字段,property是实体类的属性-->
<result column="pwd" property="password"/>
</resultMap>
id是这个resultMap 的标识,type是结果对应的实体类
result 是我们想要处理的字段,column是数据库字段,property是实体类的属性
我们这样就把返回的结果集中的pwd转换为了password
注入到User类中,就不会出现空值
ResultMap详解
子标签:constructor?,id*,result*,association*,collection*, discriminator?
属性:id,type,extends,autoMapping
属性:
- id:该标签的唯一标识
- type:映射的pojo实体类
- extends:实现存在继承关系的两个类实体的映射。extends填父类的resultMap
- autoMapping: 设置是否启动自动映射功能,自动映射功能就是自动查找与字段名小写同名的属性名,并调用setter方法。而设置为false后,则需要在
resultMap
内明确注明映射关系才会调用对应的setter方法
默认是true,也就是自动注入到实体类,如果设置为false
除了了设置好了的pwd,其他属性都没有帮我们注入
子标签:
<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="唯一的标识" type="映射的pojo对象">
<id column="表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型" property="映射pojo对象的主键属性" />
<result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到pojo对象的一个属性(须为type定义的pojo对象中的一个属性)"/>
<association property="pojo的一个对象属性" javaType="pojo关联的pojo对象">
<id column="关联pojo对象对应表的主键字段" jdbcType="字段类型" property="关联pojo对象的主席属性"/>
<result column="任意表的字段" jdbcType="字段类型" property="关联pojo对象的属性"/>
</association>
<!-- 集合中的property须为oftype定义的pojo对象的属性-->
<collection property="pojo的集合属性" ofType="集合中的pojo对象">
<id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
<result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />
</collection>
</resultMap>
- id、result标签,用于指定某个字段,基本没有区别
- association :表示一个对象,当实体类中引用了其他对象,就需要这个标签
比如一Student类中引用了Teacher类
resultMap:返回的Student结果中,返回一个Teacher对象
- collection :集合,如果返回的类型是集合,就需要使用这个标签
一个Teacher返回一个List,类型为Student
就需要collection标签
这是复杂查询,后续继续详解
缓存
当需要开启二级缓存时:
加上标签:
<cache/>
或者自定义缓存:
缓存中也有很多属性:
在后续的缓存中学习。。。
总结
Mapper.xml映射大致就这些,因为还涉及到缓存、动态sql、复杂查询,后续再深入分析
当然,可以用注解代替增删改查,后续分析
学海无涯苦作舟
都看到这了,点个赞呗(^_−)☆