文章目录
一、课程目标
【掌握】mapper映射文件的配置
【掌握】MyBatis SQL书写语法
【掌握】MyBatis 结果集处理
二、mapper基础配置
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
2.1 头标签
书写在最上用于对当前的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">
2.2 根标签
书写在mapper.xml配置文件的根标签,拥有唯一属性namespace,要求mybatis加载的多个mapper.xml不能出现相同的namespace
<mapper namespace="空间唯一标识" >
</mapper>
拥有两种书写方法:
1)自定义名称
可以使用任意不重复的名称进行命名,但是在使用时也必须通过该名进行使用(只能使用sqlsession提供的方法进行数据库操作)
2)接口完全限定名
可以使用配置的简写形式的接口名,也可以使用接口的全路径名,在使用时可以通过getMapper方法动态的获取对应的实现类,调用方法进行执行,也可以使用sqlsession提供的
2.2.1 cache二级缓存标签
书写在mapper标签中 无其他属性 可以直接书写成单标签形式,开启当前mapper的二级缓存
需要在setting 中开启二级缓存配置(如果没有开启,则只为当前mapper开启,二级缓存默认开启)
在当前mapper中的select标签中使用useCache进行二级缓存的使用默认为true,如果想指定某个select不进行缓存可以使用useCache=false关闭特定的查询缓存
在当前mapper中的修改标签中使用flushCache属性进行缓存的更新,默认为true,不需要修改,因为在进行这些操作时会修改数据导致缓存中的数据与数据库中的数据不匹配需要重新缓存.
2.2.2 sql映射标签
书写在mapper标签中,用于定义mybatis接口或方法与数据库操作的关系映射
2.2.2.1 select查询标签
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 |
resultType | 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。 |
resultMap | 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。 |
flushCache | 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false。 |
useCache | 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。 |
fetchSize | 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。 |
resultSets | 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。 |
查询的基本使用
<select id="当前空间唯一标识" 属性=值>
属性:
id 当前方法的唯一标识 在当前空间中不能重复 在对应的接口中必须存在与id相同的抽象方法
parameterType 传入的参数类型 默认会进行自动类型的匹配
resultType 返回数据的类型 如果是集合定义的是返回的集合中的数据类型
flushCache 只要执行 就会将缓存进行刷新 默认为false (不用书写)
useCache 将查询结果保存至二级缓存中 默认为true(需要开启二级缓存)
resultMap 进行复杂查询使用返回的结果集 需要额外设置
</select>
示例
<select id="selectById" parameterType="int" resultType="com.yunhe.pojo.User">
select * from t_user where id=#{id}
</select>
#{}与${}获取数据的区别
都可以进行sql语句参数的获取与填入,但是#{}mybatis在进行sql预编译时会将其转换为?只有进行赋值,${}是直接进行拼接使用相当于sql的拼接,不能防止sql注入
只有属性进行赋值时可以使用?占位符进行书写,当使用limit时就不能使用占位符而是必须使用拼接的形式进行sql的执行
2.2.2.2 Insert, Update, Delete修改标签
属性 | 描述 |
---|---|
id | 命名空间中的唯一标识符,可被用来代表这条语句。 |
parameterType | 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 |
flushCache | 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句)。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
基本使用
添加
<insert id="当前空间唯一标识" 属性=值>
属性:
id 当前方法的唯一标识 在当前空间中不能重复 在对应的接口中必须存在与id相同的抽象方法
parameterType 传入的参数类型 默认会进行自动类型的匹配
resultType 返回数据的类型 如果是集合定义的是返回的集合中的数据类型
flushCache 只要执行 就会将缓存进行刷新 默认为true (不用修改)
useGeneratedKeys 是否获取数据库自动生成的主键
keyProperty 将获取的数据存储在参数对应的属性中
</insert>
修改
<update id="当前空间唯一标识" 属性=值>
属性:
id 当前方法的唯一标识 在当前空间中不能重复 在对应的接口中必须存在与id相同的抽象方法
parameterType 传入的参数类型 默认会进行自动类型的匹配
resultType 返回数据的类型 如果是集合定义的是返回的集合中的数据类型
flushCache 只要执行 就会将缓存进行刷新 默认为true (不用修改)
useGeneratedKeys 是否获取数据库自动生成的主键
keyProperty 将获取的数据存储在参数对应的属性中
</update>
删除
<delete id="当前空间唯一标识" 属性=值>
属性:
id 当前方法的唯一标识 在当前空间中不能重复 在对应的接口中必须存在与id相同的抽象方法
parameterType 传入的参数类型 默认会进行自动类型的匹配
resultType 返回数据的类型 如果是集合定义的是返回的集合中的数据类型
flushCache 只要执行 就会将缓存进行刷新 默认为true (不用修改)
useGeneratedKeys 是否获取数据库自动生成的主键
keyProperty 将获取的数据存储在参数对应的属性中
</delete>
使用useGeneratedKeys属性与keyProperty实现获取添加后数据库自动生成的主键
useGeneratedKeys可以让mybatis获取生成的key keyProperty可以让mybatis将获取的key赋值给参数的指定字段
<insert id="insert" parameterType="com.yunhe.pojo.User" useGeneratedKeys="true" keyProperty="id">
insert into t_user (`name`,sal,birthday)values (#{name},#{sal},#{birthday})
</insert>
UserDao mapper = sqlSession.getMapper(UserDao.class);
User user = new User("阿莲", 200, new Date());
int insert = mapper.insert(user);
System.out.println(insert);
//会将自动生成的id查询后赋值给参数的指定属性
System.out.println(user);
2.2.3 resultMap 结果集映射
用来描述获取数据后与对象的映射(数据库字段与对象属性名),通常情况下使用默认的映射(数据库字段与属性名相同),但有时需要进行不同的映射,这时候就需要使用requestMap进行设置在resultType中使用。具体如下:
id:标签,用来标识主键
column:数据库字段属性 property:实体类字段属性
result:标签 ,用于其他列标识
colleaction:标签,用来标识集合属性
property:实体类字段属性
ofType:集合存储数据类型属性
column属性:用于标识查询数据列(会获取对应列数据传入相应的查询语句)
select属性:懒加载执行时调用获取数据的方法(可以调用其他mapper中的方法,通过namespace.id使用)
fetchType:局部懒加载默认fetchType="lazy"深入式 eager侵入式
association:标签,用于标识类属性
property:实体类字段属性
javaType:类类型属性
column属性:用于标识查询数据列(会获取对应列数据传入相应的查询语句)
select属性:懒加载执行时调用获取数据的方法(可以调用其他mapper中的方法,通过namespace.id使用)
fetchType:局部懒加载默认fetchType="lazy"深入式 eager侵入式
(1)将数据库列与实体类属性不一致的属性进行映射
<!-- id 当前结果集唯一表示 type当前结果集映射对象实体类 -->
<resultMap id="commodity" type="com.yunhe.pojo.Commodity">
<!-- id标签 主键唯一标识标签 property映射实体类存储数据的属性 column查询结果获取数据的列名 -->
<id property="id" column="cid"/>
<!-- result 其他列属性标签 -->
<result property="name" column="cname"/>
<result property="money" column="cmoney"/>
</resultMap>
<select id="selectAll" resultMap="commodity">
select *
from commodity
</select>
(2)将复杂映射进行一对一处理
<resultMap id="commodity_order" type="com.yunhe.pojo.Commodity">
<!-- id标签 主键唯一标识标签 property映射实体类存储数据的属性 column查询结果获取数据的列名 -->
<id property="id" column="cid"/>
<!-- result 其他列属性标签 -->
<result property="name" column="cname"/>
<result property="money" column="cmoney"/>
<!-- association属性标签 当对象中存在在定义类型属性时进行映射 -->
<!-- property当前类中属性的名字 javaType当前类中属性的类型 -->
<association property="order" javaType="com.yunhe.pojo.Order">
<id property="id" column="oid"/>
<result property="time" column="createtime"/>
</association>
</resultMap>
<select id="selectAllAndOrder" resultMap="commodity_order">
select c.cid,c.cname,c.cmoney,o.oid,o.createtime from `order` o INNER JOIN order_commodity oc on o.oid=oc.oid INNER JOIN commodity c on oc.cid = c.cid
</select>
(3)将复杂数据一对多映射进行处理
<resultMap id="order_commodity" type="com.yunhe.pojo.Order">
<id property="id" column="oid"/>
<result property="time" column="createtime"/>
<!-- association属性标签 当对象中存在在定义集合类型属性时进行映射 -->
<!-- property当前类中集合属性的名字 ofType当前类中集合存储数据类型的类型 -->
<collection property="list" ofType="com.yunhe.pojo.Commodity">
<!-- id标签 主键唯一标识标签 property映射实体类存储数据的属性 column查询结果获取数据的列名 -->
<id property="id" column="cid"/>
<!-- result 其他列属性标签 -->
<result property="name" column="cname"/>
<result property="money" column="cmoney"/>
</collection>
</resultMap>
<select id="selectAllAndCommodity" resultMap="order_commodity">
select o.oid,o.createtime,c.cid,c.cname,c.cmoney from `order` o,commodity c ,order_commodity oc where o.oid= oc.oid and c.cid =oc.cid
</select>
(4)将复杂数据进行一对多对多映射处理
<resultMap id="user_order_commodity" type="com.yunhe.pojo.User">
<id property="id" column="uid"/>
<result property="username" column="uusername"/>
<result property="password" column="upassword"/>
<collection property="orders" ofType="com.yunhe.pojo.Order">
<id property="id" column="oid"/>
<result property="time" column="createtime"/>
<collection property="list" ofType="com.yunhe.pojo.Commodity">
<!-- id标签 主键唯一标识标签 property映射实体类存储数据的属性 column查询结果获取数据的列名 -->
<id property="id" column="cid"/>
<!-- result 其他列属性标签 -->
<result property="name" column="cname"/>
<result property="money" column="cmoney"/>
</collection>
</collection>
</resultMap>
<select id="selectAllAndOrderAndCommodity" resultMap="user_order_commodity">
select u.uid,u.upassword,u.uusername,o.oid,o.createtime ,c.cid,c.cname,c.cmoney from `user` u ,`order` o ,commodity c ,user_order uo ,order_commodity oc where u.uid=uo.uid and uo.oid=o.oid and o.oid=oc.oid and oc.cid=c.cid
</select>