zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring boot(四)之保存数据到数据库

2023-09-11 14:17:51 时间

Spring boot(四)之保存数据到数据库

接着上篇Springboot(三)之使用JdbcTemplate访问数据库 的例子,回顾上篇的例子,主要时配料ingredients的查找和保存。
这次我们在前端“制作饺子”来让后端保存到数据库,主要是保存dumping数据,并且在dumping_ingredients表中将饺子dumping所要的配料ingredients映射起来。

借助JdbcTemplate,介绍两种保存数据的方法
(1)直接使用update()方法
(2)使用SimpleJdbcInsert包装器类

一、直接使用update()方法
定义DumpingRepository接口

public interface DumpingRepository {
    // 保存饺子的数据
    Dumping save(Dumping dumping);
    
}

保存dumping时候需要同时将与改dumping关联的配料保存到dumping_ingredients表中。

@Repository
public class JdbcDumpingRepository implements DumpingRepository{
    private JdbcTemplate jdbc;
    
    @Autowired
    public JdbcDumpingRepository(JdbcTemplate jdbc){
        this.jdbc = jdbc;
    }

    @Override
    public Dumping save(Dumping dumping) {
  		long dumpingId = saveDumpingInfo(dumping)
        dumping.setId(dumpingId);
        //轮询dumping中的ingredients,调用saveIngredientsToDump()保存到dumping_ingredients表中
        for (Ingredients ingredients : dumping.getIngredients()){
            saveIngredientsToDump(ingredients, dumpingId);
        }

        return dumping;
    }
	//获取数据库自增生成的id
    private Long saveDumpingInfo(Dumping dumping){
        PreparedStatementCreator psc = new PreparedStatementCreatorFactory(
                "insert into Dumping(name,place) values (?,?)",
                Types.VARCHAR,Types.VARCHAR		//两个?的类型
        ).newPreparedStatementCreator(  //接受一个数组参数
                Arrays.asList(
                        dumping.getName(),
                        dumping.getPlace()
                )	//上面两个?的所要保存的值
        );
        KeyHolder keyHolder = new GeneratedKeyHolder();
        //update()接受一个PreparedStatementCreator和一个keyHolder,keyHolder会提供生成的id
        jdbc.update(psc,keyHolder);
		//放回数据库生成的id
        return keyHolder.getKey().longValue();
    }

     private void saveIngredientsToDump(Ingredients ingredients,Long dumpingId){
        jdbc.update("insert into dumping_ingredients(dumping,ingredients) values (?,?)",dumpingId,ingredients.getId());
     }

}

在控制器中注入DumpingRepository。比较简单就不再写。

二、使用SimpleJdbcInsert插入数据

先看代码:

@Repository
public class JdbcDumpingRepository implements DumpingRepository{
    private JdbcTemplate jdbc;
    private SimpleJdbcInsert dumpInsert;
    private SimpleJdbcInsert dumpIngreInsert;
    private ObjectMapper objectMapper;

    @Autowired
    public JdbcDumpingRepository(JdbcTemplate jdbc){
        //构建两个SimpleJdbcInsert实例
        this.dumpInsert = new SimpleJdbcInsert(jdbc)
                .withTableName("dumping")
                .usingGeneratedKeyColumns("id");    //id属性由数据库提供
        this.dumpIngreInsert = new SimpleJdbcInsert(jdbc)
                .withTableName("dumping_ingredients");
        this.objectMapper = new ObjectMapper();
    }



  @Override
  public Dumping save(Dumping dumping) {
    long dumpingId = saveDumpDetails(dumping);
    dumping.setId(dumpingId);
    for(Ingredients ingredients : dumping.getIngredients()){
        saveDumpIngredients(ingredients,dumpingId);
    }
        return  dumping;
}
     private long saveDumpDetails(Dumping dumping){
         @SuppressWarnings("unchecked")
         Map<String,Object> values =
                 objectMapper.convertValue(dumping,Map.class);
         long dumpingId = dumpInsert.executeAndReturnKey(values)
                 .longValue();
         return dumpingId;
     }

     private void saveDumpIngredients(Ingredients ingredients,Long dumpingId){
         Map<String, Object> values = new HashMap<>();
         values.put("dumping", dumpingId);
         values.put("ingredients",ingredients.getId());
         dumpIngreInsert.execute(values);
     }
}

讲解:
1、 因为要在两个表中保存数据,所以用JdbcTemplate构建两个SimpleJdbcInsert 实例,还创建了Jackson中的ObjectMapper类的一个实例。
save()方法实际上没有任何保存内容,将实际的持久化任务交给saveDumpDetails()和saveDumpIngredients().

2、 SimpleJdbcInsert 有两个方法来执行数据插入操作:executeAndReturnKey()和execute(),它们都接受Map<String, Object>作为参数。其中Map的key对应表中的要插入数据的列名,Map中的value则对应要插入到列中的实际值。

3、 Dumping有很多属性,且与表中对应的列有着相同的名。所以可以使用Jackson中的ObjectMapper及其convertValue()方法。将Dumping转换成Map。Map中的key就代表列名,value代表值。也可以使用其它技术来构建Insert对象所需的Map来替换对ObjectMapper的使用。

4、 executeAndReturnKey(),会以Number对象形式返回数据库中生成的id,调用longValue(), 将返回值转成long类型。

5、 在saveDumpIngredients()方法中,就直接创建一个Map,并设置相应的值。

最后也是注入到控制器中即可。