《Spring实战(第5版)》第三章3.1代码的各种问题

1.Order类缺少tacos属性和addDesign方法

代码如下:

package tacos;

import lombok.Data;
import org.hibernate.validator.constraints.CreditCardNumber;

import javax.validation.constraints.Digits;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.util.ArrayList;
import java.util.Date;


@Data
public class Order {
    private Long id;
    private Date placedAt;
    private ArrayList<Taco> tacos = new ArrayList<>();

    public void addDesign(Taco design) {
        this.tacos.add(design);
    }

    @NotBlank(message = "Name is required")
    private String name;
    @NotBlank(message = "Street is required")
    private String street;
    @NotBlank(message = "City is required")
    private String city;
    @NotBlank(message = "State is required")
    private String state;
    @NotBlank(message = "Zip code is required")
    private String zip;
    @CreditCardNumber(message = "Not a valid credit card number")
    private String ccNumber;
    @Pattern(regexp = "^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$",message = "Must be formatted MM/YY")
    private String ccExpiration;
    @Digits(integer = 3,fraction = 0,message = "Invalid CVV")
    private String ccCVV;
}

2.数据库字段名与Order类属性不相同

因为代码用了ObjectMapper及其convertValue()方法了,所以要求Order属性名和对应数据库表列名相同。但之前的sql文件创建order表没做到这一点。应如下:

create table if not exists Taco_Order(
    id identity,
    name varchar(50) not null,
    street varchar(50) not null,
    city varchar(50) not null,
    state varchar(2) not null,
    zip varchar(10) not null,
    ccNumber varchar(16) not null,
    ccExpiration varchar(5) not null,
    ccCVV varchar(3) not null,
    placedAt timestamp not null
);

3.JdbcTacoRepository的keyHolder.getKey().longValue()空指针问题

要加一句:preparedStatementCreatorFactory.setReturnGeneratedKeys(true);
代码如下:

package tacos.data;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import tacos.Ingredient;
import tacos.Taco;


import java.sql.*;
import java.util.Arrays;
import java.util.Date;


@Repository
public class JdbcTacoRepository implements TacoRepository {
    private JdbcTemplate jdbc;

    @Autowired
    public JdbcTacoRepository(JdbcTemplate jdbc) {
        this.jdbc = jdbc;
    }

    @Override
    public Taco save(Taco taco) {
        long tacoId = saveTacoInfo(taco);
        taco.setId(tacoId);
        for (Ingredient ingredient : taco.getIngredients()) {
            saveIngredientToTaco(ingredient, tacoId);
        }
        return taco;
    }

    private long saveTacoInfo(Taco taco) {
        taco.setCreatedAt(new Date());
        //下面这行原答案错误。
        //PreparedStatementCreator psc = new PreparedStatementCreatorFactory("insert into Taco (name, createdAt) values (?,?)", Types.VARCHAR, Types.TIMESTAMP).newPreparedStatementCreator(Arrays.asList(taco.getName(), new Timestamp(taco.getCreatedAt().getTime())));

        PreparedStatementCreatorFactory preparedStatementCreatorFactory =
                new PreparedStatementCreatorFactory(
                        "INSERT into Taco (name,createdAt) values (?,?)",
                        Types.VARCHAR,Types.TIMESTAMP
                );
        preparedStatementCreatorFactory.setReturnGeneratedKeys(true);       //不加这句话会导致keyHolder.getKey()获取不到id
        PreparedStatementCreator psc = preparedStatementCreatorFactory.newPreparedStatementCreator(
                Arrays.asList(
                        taco.getName(),
                        new Timestamp(taco.getCreatedAt().getTime())
                )
        );


        KeyHolder keyHolder=new GeneratedKeyHolder();
        jdbc.update(psc,keyHolder);
        return keyHolder.getKey().longValue();
    }

    private void saveIngredientToTaco(Ingredient ingredient ,long tacoId){
        jdbc.update("insert  into Taco_Ingredients (taco,ingredient)"+"values (?,?)",tacoId,ingredient.getId());
    }

}

4.Taco类getIngredients()返回值问题

因为在JdbcTacoRepository中是这么使用Taco类的getIngredients()方法的:for (Ingredient ingredient : taco.getIngredients())
所以要更改Taco类的属性:

private List<Ingredient> ingredients;

但与之而来的是页面与后端的转换问题。表单中的Ingredient都是String类型,而此时没有办法将String类型转化为Ingredient,需要配置Converter类将Sring转化为Ingredient类。
代码如下:

package tacos;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import tacos.data.IngredientRepository;

@Component
public class IngredientByIdConverter implements Converter<String, Ingredient> {

    private IngredientRepository ingredientRepo;

    @Autowired
    public IngredientByIdConverter(IngredientRepository ingredientRepo) {
        this.ingredientRepo = ingredientRepo;
    }

    @Override
    public Ingredient convert(String id) {
        return ingredientRepo.findOne(id);
    }
}

5.H2数据库的访问

启动程序后,用链接:http://localhost:8080/h2-console进行访问。
在程序的控制台日志中找到类似:
H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:0409e967-692c-4378-868e-d9790aeff5ca'的内容。
at后面引号中的名称即你此次运行创建的内存数据库,在h2-console中JDBC URL中填入此字符串,用户名密码都为默认(sa,空)并连接,即可访问数据库。
这种方式下,数据库名(JDBC URL)每次运行都会变动。
除此之外,还可以在application.properties中设置JDBC URL,账号,密码,驱动等。并用设置的信息进行登录。

6.其他

因为加了验证,所以信用卡要用正确的测试卡号,如:5105105105105100

验证错误时,在DesignTacoController的processDesign中直接放回“design”是无法加载配料数据的。这是小的错误。而且Taco的配料属性的检验长度不能为0也是无法生效的。

    @PostMapping
    public String processDesign(@Valid Taco design, Errors errors,@ModelAttribute Order order) {
        if (errors.hasErrors()) {
            return "design";        //太简单了,无法加载数据
        }
        Taco saved=designRepo.save(design);
        order.addDesign(saved);

        return "redirect:/orders/current";
    }
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
Spring实战(第5)》是一本关于Spring框架的实践指南。该书以深入浅出的方式介绍了Spring的核心概念和实际应用,帮助读者理解并运用Spring框架解决实际问题。 该书的内容包括Spring的基本原理、IOC(控制反转)和DI(依赖注入)的实现方式,AOP(面向切面编程)的原理和应用,Spring MVC框架的使用,Spring Boot的快速开发方法以及Spring数据访问和集成测试等。除了介绍每个概念的理论基础,书中还提供了大量的实例和示例代码,帮助读者更好地理解和应用Spring框架。 《Spring实战(第5)》与前几相比,主要更新了Spring 5的新特性和最佳实践。其中,对于Spring Boot的介绍更加详细全面,并对Spring Cloud等微服务相关的内容进行了扩展。此外,书中还讲解了如何构建RESTful API,使用WebSocket和SSE进行实时通信以及使用Spring Security进行安全管理等。 该书适合已经具备一定Java开发经验的读者阅读,无论是初学者还是有一定Spring框架经验的开发者都能从中受益。读者可以通过该书系统地学习Spring框架的知识,并在实践中应用。无论是开发Web应用、企业级应用还是微服务架构,读者都可以从中找到实用的技巧和方法。 总之,《Spring实战(第5)》是一本权威的Spring框架实践指南,对于想要学习和应用Spring框架的开发者来说是一本非常有价值的书籍。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值