SpringInAction第三章笔记 --使用数据

相关代码及笔记于 https://github.com/AganRun/SpringInAction

第三章 使用数据

JDBC

初始化/预置 SQL

如果在应用的根类路径下存在明为schema.sql的文件,那么在应用启动的时候将会基于数据库执行这个文件中的SQL
放在src/main/resources下即可。

可能还希望预加载一些数据,可以把SQL命名为data.sql同样放到此目录下

注:SpringBoot2.0之后,需要加入spring.datasource.initialization-mode=always

JDBC save获得ID

  • 可以使用带有preparedStatementCreator和KeyHolder的update方法
public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder);

使用步骤:

  1. 先创建一个PreparedStatementCreatorFactory
  2. SQL 传递给它,包含参数的类型
  3. 调用工厂的newPreparedStatementCreator()
  4. 传入对象以及KeyHolder
PreparedStatementCreator psc = new PreparedStatementCreatorFactory(
                "insert into taco (name, createAt) values (?, ?)", Types.CHAR, Types.DATE
        ).newPreparedStatementCreator(
                Arrays.asList(taco.getName(), new Timestamp(taco.getCreateAt().getTime()))
        );
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(psc, keyHolder);
  • 使用SimpleJdbcInsert(相比上一种,极大得简化的代码逻辑)
    它有两个很重要的插入方法,execute()和executeAndReturnKey()
    参数就是一个Map,key为列名,value为值。可以使用Jackson的ObjectMapper的convertValue()方法直接构建出一个Map
// 初始化
this.orderTacoInserter = new SimpleJdbcInsert(jdbcTemplate)
                .withTableName("Taco_Order_Tacos");

//使用
@SuppressWarnings("unchecked")
Map<String, Object> values = objectMapper.convertValue(order, Map.class);
values.put("placeAt", order.getPlaceAt());  //因为时间会默认转为Long
long orderId = orderInserter.executeAndReturnKey(values).longValue();

JPA

JPA需要实体有一个无参的构造器

@PrePersist

createdAt()添加了PrePersist注解,作为了一个回调方法
在持久化之前,会使用这个方法将createdAt方法设置为当前的日期和时间

@Data
@NoArgsConstructor
@Entity
public class Taco {
    private Date createdAt;
    ...
    @PrePersist
    void createAt() {
        this.createdAt = new Date();
    }
}

JPA方法命名查询

JPA在进行查询方法命名时,会将get、read和find视为同义词,都是用来获取一个或多个实体的
SpringData会忽略主体中大部分的单词,你尽可以将方法命名为readPuppiesBy...

SpringBoot启动任务

可以注入CommandLineRunner类及其实现类的Bean,Spring启动时会扫描到这些类,并执行其中的run方法
最简单的Demo,在启动类中加个注入

@SpringBootApplication
public class TacoCloudApplication {

    public static void main(String[] args) {
        SpringApplication.run(TacoCloudApplication.class, args);
    }

    @Bean
    public CommandLineRunner dataLoader(IngredientRepository repo) {
        return new CommandLineRunner() {
            @Override
            public void run(String... args) throws Exception {
                repo.save(new Ingredient("FLTO", "Flour Tortilla", Type.WRAP));
            }
        };
    }
}

如果有多个启动任务,可以创建多个CommandLineRunner的子类
执行顺序由@Order指定,优先级是按value值从小到大顺序

第三章小结

  • JdbcTemplate可以简化JDBC的使用
  • 当需要知道新生成的ID的值时,可以使用PreparedStatementCreator和KeyHolder
  • 简化数据插入===>SimpleJdbcInsert
  • JPA极大简化持久化操作,只需编写Repository接口
posted @ 2020-06-14 18:38  浮梦  阅读(175)  评论(0编辑  收藏  举报