1.自动获取自增主键的id值
2. xml配置sql语句文件中使用resultMap和resultType
3..使用动态sql标签( <foreach> , <if> , 其他)
目录
一、自动获取编号的id值
在XML文件中,在<insert>
标签上配置useGeneratedKeys="true"
和keyProperty="属性名"
这2个属性,就可获取插入的新数据的自动编号的主键值!
<!-- int insert(Album album); -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO album (
name, description, sort
) VALUES (
#{name}, #{description}, #{sort}
)
</insert>
二、查询详情数据
1.新建POJO实体类
不使用原实体类封装查询结果原因:
由于查询时,并不会查询全部字段的值,所以,实体类中的某些属性值会是
null
,当方法的调用者得到结果对象,对于为null
的值,无法区分到底是“没有查询此字段的值”还是“查询了此字段,但是确实没有值”在关联查询时,没有任何实体类可以封装多表查询结果
新建POJO实体类的名称参考建议(来自《阿里巴巴Java开发手册》):
- 数据对象:xxxDO,xxx 即为数据表名
- 数据传输对象:xxxDTO,xxx 为业务领域相关的名称
- 展示对象:xxxVO,xxx 一般为网页名称
- POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO
关于常见后缀:
- DO:Data Object,即“数据对象”
- DTO:Data Transfer Object,即“数据传输对象”
- VO:View Object,即“视图对象”,或:Value Object,即“值对象”
2.<resultMap>标签
当Mybatis处理查询的结果集时,会自动将列名(Column)与属性名(Property)相同的数据进行封装,例如,将查询结果集中名为name
的数据封装到对象的name
属性中,并且,默认情况下,对于列名与属性名不同的数据,不予处理!
查询结果集中的列名(Column)默认是字段名(Field),而字段名是设计数据表时指定的。
解决方法:
在XML文件中,可以配置<resultMap>
标签
此标签的作用就是:指导Mybatis将查询结果集中的数据封装到对象中。
<resultMap id="StandardResultMap" type="cn.com.example.product.pojo.vo.BrandStandardVO">
<result column="product_count" property="productCount"/>
<result column="comment_count" property="commentCount"/>
<result column="positive_comment_count" property="positiveCommentCount"/>
</resultMap>
同样在<select>标签上,将resultType 改为 resultMap,属性值为此标签的id
<select id="getStandardById" resultMap="StandardResultMap">
sql语句...
</select>
resultMap可以复用: 其他的查询语句也是用到了相同的pojo实体类,只需要相同配置即可
3.动态SQL:<foreach>标签
作用 : 根据参数的不同,生成不同的SQL语句(相当于增强for循环)
实现用途 : 根据若干个id批量删除相册数据。
Mapper接口中抽象方法的参数:
int deleteByIds(List<Long> ids);
int deleteByIds(List[] ids);
int deleteByIds(Long... ids); 可变长参数本质也是数组!
Xml配置SQL语句
删除语句1: DELETE FROM pms_album WHERE id=? OR id=? ... OR id=?
<!-- int deleteByIds(Long[] ids); -->
<delete id="deleteByIds">
DELETE FROM pms_album WHERE
<foreach collection="array" item="id" separator=" OR ">
id=#{id}
</foreach>
</delete>
删除语句2: DELETE FROM pms_album WHERE id IN (?, ?, ... ?)
<!-- int deleteByIds(Long[] ids); -->
<delete id="deleteByIds">
DELETE FROM pms_album WHERE id IN (
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</delete>
<foreach>标签属性配置
collection
:表示被遍历的参数列表,如果抽象方法的参数只有1个,当参数类型是List
集合类型时,当前属性取值为list
,当参数类型是数组类型时,当前属性取值为array
item
:用于指定遍历到的各元素的变量名,并且,在<foreach>
的子级,使用#{}
时的名称也是当前属性指定的名字separator
:用于指定遍历过程中各元素的分隔符(或字符串等)
4.动态SQL:<if>标签
xml文件中更新的sql语句,无法实现只修改部分字段的值 , 在执行sql语句时会把原有的数据更新为null , 不符合预期!
<!-- int updateById(Album album); -->
<update id="updateById">
UPDATE
pms_album
SET
name=#{name},
description=#{description},
sort=#{sort}
WHERE
id=#{id}
</update>
解决办法: 在 set语句中每个字段使用 <if>标签包括
<set>
<if test="name != null">
name=#{name},
</if>
<if test="description != null">
description=#{description},
</if>
<if test="sort != null">
sort=#{sort},
</if>
</set>
<set>标签会自动解决 参数 遗留的','问题,并自动补全
5. 动态SQL:其它
在Mybatis中,<if>
标签并没有对应的类似Java中的else
标签!如果需要实现类似Java中if ... else ...
的效果,可以使用2个条件完全相反的<if>
标签,例如:
<if test="name != null">
某代码
</if>
<if test="name == null">
另外一段代码
</if>
以上做法的缺点在于:实际上执行了2次条件的判断,在性能略微有浪费。或者,使用<choose>
系列标签,以实现类似if ... else ...
的效果:
<choose>
<when test="判断条件">
满足条件时的SQL片段
</when>
<otherwise>
不满足条件时的SQL片段
</otherwise>
</choose>