自定义sql语句
1…xml文件的标签解析
<mapper
-------------------namespace命名空间可以理解为sqlid的前缀,目的是为了保证sql语句的唯一性(值为mapper接口的全路径名)
namespace="。。。。。">
-------------------resultMap 代表返回值数据库类型和java类型的映射,type值为返回的一个pojo对象的全路径名
<resultMap id="BaseResultMap" type="。。。。。">
-------------------constructor 构造器代表的是type中pojo对象的参数(包含列名和java类型和sql类型)
<constructor>
<idArg column="id" javaType="java.lang.Long" jdbcType="BIGINT" />
</constructor>
</resultMap>
-------------------sql标签代表sql语句片段
<sql id="Base_Column_List">
id, gmt_create, gmt_modified, title, summary,
</sql>
-------------------select标签(代表查找的sql语句)中id带表命名空间中接口中定义的方法答方法名
parameterType代表接口方法的入参(可以为基本类型int,String,也可以是简单对象类型,或者集合)
-------------------resultmap属性代表resultmap标签中的id值(这样就能处理sql语句的返回值)
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
-------------------真正的查找sql语句自定义书写开始
select
-------------------include引用sql片段
<include refid="Base_Column_List" />
from hotel_news
where id = #{id,jdbcType=BIGINT}
</select>
-------------------delete标签代表删除的sql语句
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
-------------------真正的删除sql语句自定义书写开始
delete from hotel_news
-------------------使用ognl表达式#{ }或者${ }来解析parameterType中的基类型参数或者是简单对象参数,
where id = #{id,jdbcType=BIGINT}
</delete>
-------------------insert标签代表插入的sql语句
-------------------useGeneratedKeys标识自动生成主键
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.alitrip.hotel.dataplus.domain.dataobject.HotelNewsDO" useGeneratedKeys="true">
-------------------真正的插入sql语句自定义书写开始
insert into hotel_news (gmt_create)
values (#{gmtCreate,jdbcType=TIMESTAMP})
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.alitrip.hotel.dataplus.domain.dataobject.HotelNewsDO" useGeneratedKeys="true">
insert into hotel_news
-------------------trim 标签表示为标签包含的sql语句添加前缀(prefix)后缀(suffix),去除多余的前缀(prefixOverrides一般很少用),去除多余的后缀(suffixOverrides),suffixOverrides=","标识去除后缀中最后一个,
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="gmtCreate != null">
gmt_create,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="gmtCreate != null">
#{gmtCreate,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
-------------------update标签标明更新语句
<update id="updateByExampleSelective" parameterType="map">
-------------------真正的更新语句手动编写
update hotel_news
-------------------set标签重新给对象属性赋值
<set>
-------------------增量更新
<if test="record.id != null">
id = #{record.id,jdbcType=BIGINT},
</if>
</set>
</update>
<update id="updateByPrimaryKey" parameterType="com.alitrip.hotel.dataplus.domain.dataobject.HotelNewsDO">
-------------------全量更新
update hotel_news
set gmt_create = #{gmtCreate,jdbcType=TIMESTAMP},
gmt_modified = #{gmtModified,jdbcType=TIMESTAMP},
title = #{title,jdbcType=VARCHAR},
summary = #{summary,jdbcType=VARCHAR},
published_date = #{publishedDate,jdbcType=TIMESTAMP},
news_source = #{newsSource,jdbcType=INTEGER},
url = #{url,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>
2.#{ }和${ }的区别
- #{ }在预编译的时候会吧参数使用一个占位符?代替,进入数据库后会把?替换成具体的属性值,需要进行数据类型装换,能有效防止sql注入
- ${ }可能发生sql注入,因为在动态解析的时候会把这部分sql语句当做sql片段进行sql拼接而不会发生数据类型的装换,到数据库之后就会变成一个已经定型的sql语句了
3.对集合的处理(数组,list,map)
- foreach元素的属性主要有 item,index,collection,open,separator,close。
- collection标识参数中的属性,1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list,2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- item表示集合中每一个元素进行迭代时的别名,
- index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,
- open表示该语句以什么开始,
- separator表示在每次进行迭代之间以什么符号作为分隔符,
- close表示以什么结束。
<if test="hotelIds != null and hotelIds.size() > 0">
AND hcc.hotel_id in
<foreach collection="hotelIds" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
4.where标签
<where>
1=1
</where>
等效于
<where>
and 1=1
</where>
等效于 where 1=1;where标签可以自动处理第一个and条件(去除and)
5.自增主键返回到简单对象中
<!-- selectKey 标签实现主键返回 -->
<!-- keyColumn:主键对应的表中的哪一列 -->
<!-- keyProperty:主键对应的pojo中的哪一个属性 -->
<!-- order:设置在执行insert语句前执行查询id的sql,在执行insert语句之后执行查询id的sql -->
<!-- resultType:设置返回的id的类型 -->
<selectKey keyColumn="id" keyProperty="id" order="AFTER"
resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
6.sql语句执行顺序
- 第一步:执行FROM
-----------分组前的数据约束(不满足条件不参加分组) - 第二步:WHERE条件过滤
-------------分组可以根据(GROUP_CONCAT 可以查看分组后某个属性数据的集合) - 第三步:GROUP BY分组(可以按多个属性的先后顺序分组)
-------------having 是在分组后对数据进行过滤,where 是在分组前对数据进行过滤 - 第四步:HAVING条件过滤
-----------排序(按照属性正序或倒序排列) - 第五步:执行ORDER BY 排序
7.多种连接查询(相当于把两张表的数据平再在一起形成一个临时表包含两张表的所有字段)
-
内连接
关键字:inner join on
语句:select * from a_table a inner join b_table bon a.a_id = b.b_id;
结果:把满足条件的a表中和b表中的字段拼接在一起的(相当于求交集) -
外连接
-
左连接
关键字:left join on / left outer join on
语句:select * from a_table a left join b_table bon a.a_id = b.b_id;
结果:以左表为主,右表为辅助(左(外)连接,左表(a_table)的记录将会全部表示出来,而右表(b_table)只会显示符合搜索条件的记录。右表记录不足的地方均为NULL。) -
右连接
关键字:right join on / right outer join on
语句:select * from a_table a left join b_table bon a.a_id = b.b_id;
结果:以右表为主,左表为辅助,与左(外)连接相反,右(外)连接,左表(a_table)只会显示符合搜索条件的记录,而右表(b_table)的记录将会全部表示出来。左表记录不足的地方均为NULL。 -
全连接(左连接+右连接+去重)
关键字:unique
语句:select * from a_table a left join b_table bon a.a_id = b.b_id
union
select * from a_table a right join b_table bon a.a_id = b.b_id ;
结果:把左连接和右连接的结果放在一起去重
备注:特殊的函数
1.行转列group_concat()
2,去重distinct