在POJO中干掉属性ID构成的集合字段

本文介绍了如何利用SpringConverter在处理表单提交的ID列表时,直接转换为对象集合,避免了额外的查询操作。通过自定义转换器 IngredientByIdConverter,将前端提交的IDs转换为Ingredient对象,简化了后端处理过程,提高了效率。

使用SpringConverter来优化Ids和Id构成集合的关联关系

我们在进行项目开发的时候,就会遇到这个问题, List ingredients; List ingredients; 同样都是原理集合,一个后端喜欢,一个前端喜欢。在一个POJO里面经常把这两个都写上。都按照对象的关系来说,肯定第一个我们更为青睐,数据库也好查询不是!

1、问题描述

1.1、form表单提交了多个相同name值

以一个煎饼果子为例,制作煎饼果子需要多种原料就有了下方的form表单数据

      <input type="checkbox" name="ingredients" th:value="${item.id}" />
      <input type="checkbox" name="ingredients" th:value="${item.id}" />
      <input type="checkbox" name="ingredients" th:value="${item.id}" />
       <input type="checkbox" name="ingredients" th:value="${item.id}" />

1.2、而我们一般用数组接收

举个例子比如说得到id数组,进行批量删除操作。现在我们就给煎饼果子添加原料构成的ID集合

package com.wnx.toca.domain;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 煎饼果子
 * @author wangnaixing
 * @Classname ChineseHamburger
 * @Description TODO
 * @Date 2021/12/14 22:43
 * @Created by wangnaixing
 */
@Data
public class ChineseHamburger implements Serializable {
    /**
     * 自增主键
     */
    private Long id;
    /**
     * 制作人姓名
     */
    private String name;
    /**
     * 创建时间
     */
    private Date created;

    //=======附加属性==========//
    /**
     * 原料集合
     */
    List<Long> ingredients;
    //=======附加属性==========//

}

1.3、我们现在要保存这个煎饼果子噢

我们常规想法一定是:

  • 先保存煎饼果子信息
  • 再添加煎饼果子和原料的关联关系

2、以前我的处理

这里以我已Spring的JdbcTemplate为持久层操作为例子哈

2.1、在原料的Dao上定义上根据ID查询原料的方法

    /**
     * 根据ID查询煎饼果子原料
     * @param id
     * @return
     */
    Ingredient findById(Long id);
  /**
     * 根据ID查询煎饼果子原料
     * @param id
     * @return
     */
    @Override
    public Ingredient findById(Long id) {
        return jdbcTemplate.queryForObject("select id,name,type from ingredient where id = ?",this::mapRowToIngredient,id);
    }

2.2、定义添加煎饼果子的方法

  • 操作jdbctemplate进行新增煎饼果子,得到自增主键

  • 注入原料的Serivce,遍历煎饼果子属性原料id集合,根据ID查询原料

  @Repository
public class JdbcChineseHamburgerDaoImpl implements ChineseHamburgerDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private IngredientService ingredientService;

  /**
     * 新增煎饼果子
     * @param chineseHamburger
     * @return
     */
    @Override
    public ChineseHamburger save(ChineseHamburger chineseHamburger) {
        //先新增煎饼果子表记录
        long chineseHamburgerId = this.saveChineseHamburger(chineseHamburger);

        List<Long> ingredientIds = chineseHamburger.getIngredients();
        List<Ingredient> ingredientList = new ArrayList<>();

        for (Long ingredientId : ingredientIds) {
            //调用持久层查询煎饼果子原料
            Ingredient ingredient = ingredientService.findById(ingredientId);
            ingredientList.add(ingredient);
        }

        //再增加煎饼果子和煎饼果子调料关系表记录
        ingredientList.forEach(ingredient -> {this.saveChineseHamburgerIngredientRelation(ingredient,chineseHamburgerId);});

        return chineseHamburger;
    }
}

2.3、抽取私有方法

    /**
     * 保存煎饼果子,返回自增的主键
     * @return
     */
    private long saveChineseHamburger(ChineseHamburger chineseHamburger){
        chineseHamburger.setCreated(new Date());
        KeyHolder keyHolder = new GeneratedKeyHolder();

        //基于PreparedStatementCreator的定义的DDL
        PreparedStatementCreator creator =
                new PreparedStatementCreatorFactory(
                        "insert into chinese_hamburger(name,created) values(?,?)",
                        Types.VARCHAR, Types.TIMESTAMP
                ).newPreparedStatementCreator(
                        Arrays.asList(chineseHamburger.getName(),
                                new Timestamp(chineseHamburger.getCreated().getTime())));
        jdbcTemplate.update(creator, keyHolder);
        //得到自增主键并返回
        return keyHolder.getKey().longValue();
    }

    /**
     * 增加煎饼果子和煎饼果子调料关系表记录
     * @param ingredient
     * @param chineseHamburgerId
     */
    private void saveChineseHamburgerIngredientRelation(Ingredient ingredient,long chineseHamburgerId){

        jdbcTemplate.update(
                "insert into chinese_hamburger_ingredient_relation (chinese_hamburger_id, ingredient_id) " +
                        "values (?, ?)",
                chineseHamburgerId, ingredient.getId());
    } 

3、新做法:Converter转换器的处理

可不可以在定于domain的时候,写的原理集合是List<Ingredient>,而不是List,每次根据ID转换,这部分代码明显是恶心了。Converter转换器就可解决这个问题。

3.1、定义自定义转换器

package com.wnx.toca.converter;


import com.wnx.toca.domain.Ingredient;
import com.wnx.toca.serivce.IngredientService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;


/**
 * 煎饼果子材料和煎饼果子ID转换器
 * @author wangnaixing
 */
@Component
public class IngredientByIdConverter implements Converter<String, Ingredient> {
  @Autowired
  private IngredientService ingredientService;

  @Override
  public Ingredient convert(String id) {
    if (StringUtils.isNotBlank(id)){
      return ingredientService.findById(Long.parseLong(id));
    }
    return null;
  }

}

3.2、修改domain

package com.wnx.toca.domain;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 煎饼果子
 * @author wangnaixing
 * @Classname ChineseHamburger
 * @Description TODO
 * @Date 2021/12/14 22:43
 * @Created by wangnaixing
 */
@Data
public class ChineseHamburger implements Serializable {
    /**
     * 自增主键
     */
    private Long id;
    /**
     * 制作人姓名
     */
    private String name;
    /**
     * 创建时间
     */
    private Date created;

    //=======附加属性==========//
    /**
     * 原料集合
     */
    List<Ingredient> ingredients;
    //=======附加属性==========//

}

3.3、打印结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值