spring(DAY04)

1. 插入数据时获取自动编号的id

如果某张表的id被设计为自动编号的,在插入数据时,还可以获取自动编号的id值!

在配置SQL的<insert>标签上,配置useGeneratedKeyskeyProperty属性即可:

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
	此处省略插入数据的SQL语句
</insert>

以上配置中,useGeneratedKeys="true"表示“需要获取自动编号的id值”,而keyProperty="id"表示将id值保存到参数对象(调用插入数据的方法时使用的参数)的id属性中。

2. 根据id删除数据

删除数据的开发步骤与插入数据的相同,只是配置SQL时使用的标签应该为<delete>

【需求】根据id删除某个品牌数据。

则在BrandMapper接口中添加抽象方法:

int deleteById(Long id);

然后,在BrandMapper.xml中配置SQL:

<delete id="deleteById">
    DELETE FROM pms_brand WHERE id=#{id}
</delete>

最后,在BrandMapperTests中编写并执行测试:

@Test
void testDeleteById() {
    Long id = 1L;
    int rows = mapper.deleteById(id);
    System.out.println("根据id删除品牌完成,受影响的行数=" + rows);
}

3. 动态SQL:根据若干个id删除数据

动态SQL:允许根据参数不同,来生成不同的SQL语句。

【需求】根据若干个id删除品牌数据

需要执行的SQL语句大致是:

DELETE FROM pms_brand WHERE id=? OR id=? …… OR id=?;
DELETE FROM pms_brand WHERE id IN (?, ?, .... ?);

在以上SQL中,需要被删除的数据的id的数量是不确定的!

在实现此需求时,抽象方法可以设计为:

int deleteByIds(List<Long> ids);
int deleteByIds(Long[] ids);
int deleteByIds(Long... ids); // deleteByIds(1,2,3,4,5)

在配置SQL时,需要使用到<foreach>标签对参数进行遍历:

<!-- int deleteByIds(List<Long> ids); -->
<delete id="deleteByIds">
    DELETE FROM pms_brand WHERE id IN (
    	<foreach collection="list" item="id" separator=",">
            #{id}
    	</foreach>
    )
</delete>

关于<foreach>标签的属性:

  • collection:表示被遍历的参数对象,当抽象方法的参数只有1个时,如果参数类型是List,则此属性值为list,如果参数类型是数组(或可变参数),则此属性值为array
  • item:遍历过程中的每个元素的名称,是自定义的名称,并且,在<foreach>标签内部,使用#{}时的名称也就是此属性的值(此处自定义的名称)
  • separator:遍历过程中在值之前添加的分隔符号

完成后,在BrandMapperTests中编写并执行测试:

@Test
void testDeleteByIds() {
    List<Long> ids = new ArrayList<>();
    ids.add(2L);
    ids.add(6L);
    ids.add(7L);
    
    int rows = mapper.deleteByIds(ids);
    System.out.println("根据id批量删除品牌完成,受影响的行数=" + rows);
}

4. 动态SQL:修改数据

【需求】根据id修改品牌的数据,参数中传入了哪些属性,就修改对应的那些字段的值

需要执行的SQL语句大致是:

update pms_brand set name=?, pinyin=?, logo=?, description=? ....(修改其它字段的值) where id=?

则抽象方法可以设计为:

int updateById(Brand brand);

然后,配置SQL语句:

<update id="updateById">
    UPDATE
        pms_brand
    <set>
        <if test="name != null">
            name=#{name},
        </if>
        <if test="pinyin != null">
            pinyin=#{pinyin},
        </if>
        <if test="logo != null">
            logo=#{logo},
        </if>
        <if test="description != null">
            description=#{description},
        </if>
        <if test="keywords != null">
            keywords=#{keywords},
        </if>
        <if test="sort != null">
            sort=#{sort},
        </if>
        <if test="sales != null">
            sales=#{sales},
        </if>
        <if test="productCount != null">
            product_count=#{productCount},
        </if>
        <if test="commentCount != null">
            comment_count=#{commentCount},
        </if>
        <if test="positiveCommentCount != null">
            positive_comment_count=#{positiveCommentCount},
        </if>
        <if test="enable != null">
            enable=#{enable},
        </if>
    </set>
    WHERE
        id=#{id}
</update>

以上代码中,使用到了2个标签:

  • <if>:用于对参数的值进行判断,从而决定SQL语句中是否包含<if>子级的SQL片段
  • <set>:用于取代SET关键字,通常结合若干个<if>一起使用,可以去除更新的SQL语句中的字段列表与值最后多余的逗号

注意:<if>标签并没有匹配的类似else的标签,如果需要实现类似Java代码中的if...else...的效果,可以:

<if test="某条件">
	满足条件时的SQL片段
</if>
<if test="与以上完全相反的条件">
	满足本if时的SQL片段
</if>

以上示例可以实现类似if...else...的效果,但是,更像是if...与另一个if...,本质上是执行了2次判断的!

另外,还可以使用<choose>系列标签,真正的实现类似if...else...的效果:

<choose>
    <when test="判断条件">
    	满足条件时的SQL片段
    </when>
    <otherwise>
    	不满足条件时的SQL片段
    </otherwise>
</choose>

5. 统计查询

【需求】统计品牌表中的数据的数量

需要执行的SQL语句大致是:

SELECT count(*) FROM pms_brand;

BrandMapper接口中添加抽象方法:

int count();

BrandMapper.xml中配置SQL语句:

<select id="count" resultType="int">
    SELECT count(*) FROM pms_brand
</select>

6. 查询最多1条数据

【需求】根据id查询品牌详情

需要执行的SQL语句大致是:

SELECT 
    id, name, pinyin, logo, description, 
    keywords, sort, sales, product_count, comment_count, 
    positive_comment_count, enable 
FROM 
	pms_brand 
WHERE 
	id=?

通常,在处理查询时,并不建议使用实体类型作为查询结果,因为绝大部分查询都不需要查询表中所有的字段,如果使用实体类型,必然导致查询结果对象调用某些Getter时得到的结果会是null,并且,这些Getter的返回结果永远会是null

建议使用其它的POJO类型作为封装查询结果的类型!

常见的POJO:

  • DO:Data Object
  • DTO:Data Transfer Object
  • VO:View Object / Value Object

关于POJO的使用:

阿里巴巴Java开发手册
【参考】
领域模型命名规约
1) 数据对象:xxxDO,xxx 即为数据表名。
2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
3) 展示对象:xxxVO,xxx 一般为网页名称。
4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。

另外:

阿里巴巴Java开发手册
【强制】
类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO
正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

此次查询时,应该在项目的根包下,创建pojo.vo.BrandStandardVO类:

@Data
public class BrandStandardVO implements Serializable {
	private Long id;
    private String name;
    private String pinyin;
    private String logo;
    private String description;
    private String keywords;
    private Integer sort;
    private Integer sales;
    private Integer productCount;
    private Integer commentCount;
    private Integer positiveCommentCount;
    private Integer enable;
}

BrandMapper接口中添加抽象方法:

BrandStandardVO getStandardById(Long id);

Mybatis会自动的将查询到的结果集中的数据封装到定义的返回结果类型中,但是,在默认情况下,只能处理列名(Column)与属性名(Property)一致的情况!在规范的软件开发中,推荐使用<resultMap>来配置列与属性的映射关系:

<resultMap id="StandardResultMap" type="cn.tedu.csmall.product.pojo.vo.BrandStandardVO">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="product_count" property="productCount"/>
    <result column="comment_count" property="commentCount"/>
    <result column="positive_comment_count" property="positiveCommentCount"/>
</resultMap>

关于以上<resultMap>的配置:

  • id属性:是自定义的名称,在<select>标签中的resultMap属性的值就是对应的<resultMap>id
  • type属性:用于封装查询结果的类的全限定名
  • <id>子标签:用于配置主键的列、属性的映射关系
  • <result>子标签:用于配置普通(不是主键,也不是一对多、多对多的关联查询)的列、属性的映射关系

另外,还建议使用<sql>标签封装查询的字段列表,此标签需要与<include>标签配合使用,例如:

<select id="getStandardById" resultMap="StandardResultMap">
    SELECT
        <include refid="StandardQueryFields"/>
    FROM
        pms_brand
    WHERE
        id=#{id}
</select>

<sql id="StandardQueryFields">
    <if test="true">
        id, name, pinyin, logo, description,
        keywords, sort, sales, product_count, comment_count,
        positive_comment_count, enable
    </if>
</sql>

7. 关于IntelliJ IDEA错误的预判

问题1:使用Lombok后,不会自动提示Setter和Getter,且使用相当方法后提示错误

在IntelliJ IDEA中安装Lombok插件即可。

问题2:使用Mybatis时,尝试自动装配Mapper接口的对象时提示错误

  • 【推荐】在Mapper接口上添加@Repository注解即可
  • 【不推荐】使用@Resource替换@Autowired

另外,不使用@MapperScan,而是在每个Mapper接口上使用@Mapper也可以解决此问题!

问题3:在配置SQL的XML中,使用<sql>节点封装字段列表时提示错误

  • 【不推荐】在IntelliJ IDEA中进行配置,不检查SQL

  • 【推荐】使用某种合法的、不影响当前代码运行的代码片段,“骗”过IntelliJ IDEA即可,例如:

    <sql id="StandardQueryFields">
        <if test="true">
            id, name, pinyin, logo, description,
            keywords, sort, sales, product_count, comment_count,
            positive_comment_count, enable
        </if>
    </sql>
    

作业

实现:

  • 统计类别的数量
  • 统计相册的数量
  • 根据id查询类别详情
  • 根据id查询相册详情
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值