MyBatis 语句扩展

返回主键标签

通过入参实体类返回插入语句执行后自增的主键值,在多张表的关联操作中很有用

<insert id="getIdByAdd" parameterType="question">
	<selectKey keyProperty="id" resultType="int" order="AFTER">
		select last_insert_id();
	</selectKey>
	insert into question_copy1
	values (#{id}, #{title}, #{optionA}, #{optionB}, #{optionC}, #{optionD}, #{answer});
</insert>
参数解析:
    KeyProperty:返回的主键值放入实体类的哪个属性中(成员变量中)
    resultType:返回主键值的类型
    order:在插入语句执行前返回主键值使用BEFORE,再插入语句执行后返回主键之使用AFTER

优化mapper.xml文件的注册方式


<mappers>
	<!--非动态代理方式下的注册-->
	<mapper resource=""/>
	<!--动态代理方式下的注册-->
	<mapper class=""/>
	<!--绝对路径注册(不用)-->
	<mapper url=""/>
	<!--批量注册-->
	<package name=""/>
</mappers>

动态sql

动态 SQL 是 MyBatis 的强大特性之一,它支持咋i数据库访问过程中进行逻辑判断,循环迭代,支持代码片段的定义和引用(代码复用)
利用动态 SQL,可以彻底摆脱多条件拼接的这种痛苦
利用动态 SQL,可以有选择的更新
利用动态 SQL,批量处理
  • sql
<!-- <sql> : 定义代码片段,用来进行代码复用,可以定义所有的列明,可以定义复杂的条件 -->
<sql id="allColumns">
	id, title, optionA, optionB, optionC, optionD, answer
</sql>
  • include
<!-- <include> : 引用定义好的代码片段,它与 <sql> 标签配套使用 -->
<select id="findAll" resultType="icu.sandink.pojo.Question">
	select
	<include refid="allColumns"/>
	from question;
</select>
  • if : 用来逻辑判断
  • where
<!-- <where> : 用来进行多条件处理-->
<select id="getByCondition" parameterType="question" resultType="question">
	select
	<include refid="allColumns"/>
	from question
	<where>
		<if test="title != null and title != ''">
			and title like concat('%',#{title},'%')
		</if>
		<if test="answer != null and answer != ''">
			and answer like concat('%',#{answer},'%')
		</if>
	</where>
</select>
  • set
<!-- <set> : 有选择的更新,可以保证没有传值进来,不影响表中的数据 -->
<!-- 至少更新一个字段 -->
<update id="modifyBySet" parameterType="question">
	update question
	<set>
		<if test="title != null and title != ''">
			title = #{title},
		</if>
		<if test="optionA != null and optionA != ''">
			optionA = #{optionA},
		</if>
		<if test="optionB != null and optionB != ''">
			optionB = #{optionB},
		</if>
		<if test="optionC != null and optionC != ''">
			optionC = #{optionC},
		</if>
		<if test="optionD != null and optionD != ''">
			optionD = #{optionD},
		</if>
		<if test="answer != null and answer != ''">
			answer = #{answer},
		</if>
	</set>
	where id = #{id}
</update>
  • foreach
<!-- <foreach> : 用来进行循环遍历的,可以批量处理,批量删除,批量增加,批量更新,查询也可以使用循环 -->
<!--查询操作-->
<select id="getByIds" resultType="question">
	select
	<include refid="allColumns"/>
	from question
	where id in
	<!--
        参数解析:
            collection: 传入的数据类型,数组为'array',List集合为'list',Map集合为'map'
            item: 遍历出来的临时变量或对象
            separator: 多个变量或对象或语句之间的分隔符
            open: 整个循环遍历前面的字符串
            close: 整个循环遍历后面的字符串
    -->
	<foreach collection="array" item="id" separator="," open="(" close=")">
		#{id}
	</foreach>
</select>
<!--批量删除-->
<delete id="removeByIds">
	delete from question
	where id in
	<foreach collection="array" open="(" close=")" item="id" separator=",">
		#{id}
	</foreach>
</delete>
<!--批量增加-->
<insert id="adds">
	insert into question
	values
	<foreach collection="list" separator="," item="question">
		(#{question.id}, #{question.title}, #{question.optionA}, #{question.optionB}, #{question.optionC},
		#{question.optionD}, #{question.answer})
	</foreach>
</insert>

指定参数位置

如果实体类不能封装全部的查询条件,多条件查询使用多个参数的情况下,可以使用参数的默认下标顺序进行传值
mybatis-3.3版本和之前的版本使用#{0},#{1}方式,从mybatis3.4开始使用#{arg0}方式

<select id="findByBetweenId" resultType="question">
	select
	<include refid="allColumns"/>
	from question
	where id between #{arg0} and #{arg1}
</select>

入参是map的方式传值

使用下标予以不明确,使用map封装查询条件,使用key读取value的值
适用于实体类不能封装全部查询条件的情况下

<select id="findByBetweenId" parameterType="map" resultType="question">
	select
	<include refid="allColumns"/>
	from question
	where id between #{begin} and #{end}
</select>

返回值是map

如果返回的数据实体类不能封装,则可以通过map集合返回,但返回后的数据与实体类无关,是散的Object数据,返回的列名或别名是 key,列中的值是 value。
  • 返回一行map
<!--Map<String, Object> map=mapper.getReturnMapOne(4);-->
<select id="getReturnMapOne" resultType="map">
	select title, answer
	from question
	where id = #{id}
</select>
  • 返回多行map
<!--List<Map<String, Object>> returnMap = mapper.getReturnMap();-->
<select id="getReturnMap" resultType="map">
	select title, answer
	from question
</select> 

分页插件PageHelper

可以添加分页插件进行分页处理,分页插件设置页码和每页条数,记录所有分页相关数据,相当于是分页自动化
分页插件是用在业务逻辑层的
  • 在pom.xml文件中添加分页插件的依赖
<!--pom.xml-->
<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>5.1.10</version>
</dependency>
  • 在配置xml文件中注册分页插件(使用拦截器注册)
<!--注册pageHelper插件-->
<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
  • 使用PageHelper设置分页信息,使用PageInfo封装分页数据
public class Test {
	@Test
	public void testPageHelper() {
		//在调用查询语句之前设置PageHelper的参数
		PageHelper.startPage(6, 5);
		
		//完成查询操作
		List<Question> questions = mapper.findAll();
		
		//使用PageInfo封装分页的数据
		PageInfo<Question> info = new PageInfo<>(questions);
		
		System.out.println(info);
		//PageInfo{pageNum=6, pageSize=5, size=1, startRow=26, endRow=26, total=26, pages=6, list=Page{count=true, pageNum=6, pageSize=5, startRow=25, endRow=30, total=26, pages=6, reasonable=false, pageSizeZero=false}[Question{id=29, title='神经调节的基本方式是', optionA='反射', optionB='反应', optionC='适应', optionD='正反馈', answer='A', time=null}], prePage=5, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=8, navigateFirstPage=1, navigateLastPage=6, navigatepageNums=[1, 2, 3, 4, 5, 6]}
	}
}

列名于类中成员变量名称不一致

因为表中列的命名规范与类中成员变量的命名规范不一样,导致不一致
  • 使用别名映射
<!--
    表:
        bookid int,
        bookname varchar
    
    实体类:
        private Integer id;
        private String name;
-->
<select id="getAll" resultType="book">
	select bookid id, bookname name
	from book
</select>
  • 使用ResultMap解决
<!--手工进行映射绑定,将列名于实体类中成员变量绑定-->
<mapper namespace="icu.sandink.mapper.IBookMapper">
	<!--手工映射绑定-->
	<resultMap id="bookmap" type="book">
		<!--主键绑定-->
		<id property="id" column="booked"/>
		<!--非主键绑定-->
		<result property="name" column="bookname"/>
	</resultMap>

	<select id="getAll" resultMap="bookmap">
		select bookid, bookname
		from book
	</select>
</mapper>

表的关联关系

关联关系是有场景限定的,是有关联方向的
1)一对多关联:一个教师和多个学生,这个老师只能教这些学生,这些学生只有这一个老师来教,站在老师的角度就是一对多
2)多对一关联:多个学生和一个老师,多个学生只能有这一个老师,这个老师也只有教这多个学生,站在学生的角度就是多对一
3)一对一关联:一个人有一个身份证号,这个身份证号也只代表这一个人
4)多对多关联:车和车位,一个车可以停放任意车位,一个车位可以停放任意一辆车

一对多关联

客户对订单:一个客户可以下多个订单,这多个订单属于同一个客户。
    客户:订单 = 1 : N
    客户实体类中持有订单的集合

<mapper namespace="icu.sandink.mapper.ICustomerMapper">
	<resultMap id="customerMap" type="customer">
		<!--主键映射-->
		<id property="id" column="cid"/>
		<!--非主键映射-->
		<result property="name" column="name"/>
		<result property="age" column="age"/>
		<!--集合映射-->
		<collection property="ordersList" ofType="orders">
			<!--主键映射-->
			<id property="id" column="oid"/>
			<!--非主键映射-->
			<result property="orderNumber" column="orderNumber"/>
			<result property="orderPrice" column="orderPrice"/>
		</collection>
	</resultMap>

	<!-- ==============select============== -->
	<!--
        <interface> ICustomerMapper
        Customer getById(Integer id);
    -->
	<select id="getById" resultMap="customerMap">
		select
		c.id cid, name, age, o.id oid, orderNumber, orderPrice, customer_id
		from customer c
		join orders o on c.id = o.customer_id
		where c.id = #{id}
	</select>
</mapper>

多对一关联

订单和客户是多对一关联
订单:客户 = N : 1

<mapper namespace="icu.sandink.mapper.IOrdersMapper">
	<resultMap id="ordersMap" type="orders">
		<id property="id" column="oid"/>
		<result property="orderNumber" column="orderNumber"/>
		<result property="orderPrice" column="orderPrice"/>
		<association property="customer" javaType="customer">
			<id property="id" column="cid"/>
			<!--非主键映射-->
			<result property="name" column="name"/>
			<result property="age" column="age"/>
		</association>
	</resultMap>

	<!-- ==============select============== -->
	<!--
	    <interface> IOrdersMapper
        Orders getById(Integer id);
    -->
	<select id="getById" resultMap="ordersMap">
		select
		o.id oid, orderNumber, orderPrice, customer_id, c.id cid, name, age
		from orders o
		join customer c on o.customer_id = c.id
		where o.id = #{id}
	</select>
</mapper>

一对一关联

一个班级只有一个授课老师,一个老师也只为一个班级授课
美方都持有对方的对象

多对多关联

一本书可以隶属与多个类别,一个类别可以包含多本书
多对多关联关系是通过中间表化解关联
美方都持有另一方的集合

所有关联关系的总结:
    无论是什么关联关系,如果某方持有另一方的集合,则使用<collection>标签完成映射;
    如果某方持有另一方的对象,则使用<association>标签完成映射.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值