Spring实战(第5版)第三章代码问题
先吐槽。。。这本书代码问题是真的多!
-
application.properties
spring.thymeleaf.cache=false spring.datasource.url=jdbc:h2:mem:db;database_to_upper=false spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=root spring.datasource.password=123456 spring.datasource.schema=classpath:db/schema.sql spring.datasource.data=classpath:db/data.sql spring.h2.console.enabled=true
- 数据库初始化文件放在
resources/db/
文件夹下
- 数据库初始化文件放在
-
DesignTacoController
问题- 主要问题出在表单中的字符串如何转
Ingredient
类 design.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Taco Cloud</title> <link rel="stylesheet" th:href="@{./styles.css}"> </head> <body> <h1>Design your taco!</h1> <img th:src="@{/images/TacoCloud.png}"/> <form method="POST" th:object="${taco}"> <span class="validationError" th:if="${#fields.hasErrors('ingredients')}" th:errors="*{ingredients}">Ingredient Error</span> <div class="grid"> <div class="ingredient-group" id="wraps"> <h3>Designate your wrap:</h3> <div th:each="ingredient : ${wrap}"> <input name="ingredientsString" type="checkbox" th:value="${ingredient}"/> <span th:text="${ingredient.name}">INGREDIENT</span><br/> </div> </div> <div class="ingredient-group" id="proteins"> <h3>Pick your protein:</h3> <div th:each="ingredient : ${protein}"> <input name="ingredientsString" type="checkbox" th:value="${ingredient}"/> <span th:text="${ingredient.name}">INGREDIENT</span><br/> </div> </div> <div class="ingredient-group" id="cheeses"> <h3>Choose your cheese:</h3> <div th:each="ingredient : ${cheese}"> <input name="ingredientsString" type="checkbox" th:value="${ingredient}"/> <span th:text="${ingredient.name}">INGREDIENT</span><br/> </div> </div> <div class="ingredient-group" id="veggies"> <h3>Determine your veggies:</h3> <div th:each="ingredient : ${veggies}"> <input name="ingredientsString" type="checkbox" th:value="${ingredient}"/> <span th:text="${ingredient.name}">INGREDIENT</span><br/> </div> </div> <div class="ingredient-group" id="sauces"> <h3>Select your sauce:</h3> <div th:each="ingredient : ${sauce}"> <input name="ingredientsString" type="checkbox" th:value="${ingredient}"/> <span th:text="${ingredient.name}">INGREDIENT</span> </div> </div> <h3>Name your taco creation:</h3> <input type="text" th:field="*{name}"/> <br/> <button>Submit your taco</button> </div> </form> </body> </html>
DesignController.java
package com.yuq.taco; import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @Controller @RequestMapping("/design") @SessionAttributes("order") public class DesignTacoController { private final IngredientRepository ingredientRepo; private TacoRepository designRepo; @Autowired public DesignTacoController(IngredientRepository ingredientRepo, TacoRepository designRepo) { this.ingredientRepo = ingredientRepo; this.designRepo = designRepo; } @ModelAttribute public void addIngredientsToModel(Model model) { List<Ingredient> ingredients = new ArrayList<>(); ingredientRepo.findAll().forEach(i -> ingredients.add(i)); Ingredient.Type[] types = Ingredient.Type.values(); for (Ingredient.Type type : types) { model.addAttribute(type.toString().toLowerCase(), filterByType(ingredients, type)); } } @ModelAttribute(name = "order") public Order order() { return new Order(); } @ModelAttribute(name = "taco") public Taco taco() { return new Taco(); } @GetMapping public String showDesignForm(Model model) { return "design"; } @PostMapping public String processDesign(@Valid Taco design, Errors errors, @ModelAttribute Order order) { if (errors.hasErrors()) return "design"; Gson gson = new Gson(); for (String info : design.getIngredientsString()) { Ingredient x=gson.fromJson(info, Ingredient.class); design.addIngredients(x); } design.setCreatedAt(new Date()); Taco saved = designRepo.save(design); order.addDesign(saved); return "redirect:/orders/current"; } private List<Ingredient> filterByType(List<Ingredient> ingredients, Ingredient.Type type) { return ingredients.stream().filter(x -> x.getType().equals(type)).collect(Collectors.toList()); } }
Ingredient.java
package com.yuq.taco; import lombok.Data; import lombok.RequiredArgsConstructor; @Data @RequiredArgsConstructor public class Ingredient { private final String id; private final String name; private final Type type; public static enum Type { WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE } @Override public String toString() { return "{'id':'" + id + "\'" + ", 'name':'" + name + "\'" + ", 'type':'" + type + "\'}"; } }
- 添加
Gson
依赖
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.1</version> </dependency>
package com.yuq.taco; 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 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 design) { long tacoId=saveTacoInfo(design); design.setId(tacoId); for(Ingredient ingredient:design.getIngredients()){ saveIngredientToTaco(ingredient,tacoId); } return design; } private long saveTacoInfo(Taco taco){ // PreparedStatementCreator psc = new PreparedStatementCreatorFactory( // "insert into Taco (name,createdAt) values (?,?);", // Types.VARCHAR,Types.TIMESTAMP // ).newPreparedStatementCreator(Arrays.asList(taco.getName(),new Timestamp(taco.getCreatedAt().getTime()))); // // KeyHolder keyHolder=new GeneratedKeyHolder(); // jdbc.update(psc,keyHolder); String sql = "insert into Taco (name,createdAt) values (?,?);"; KeyHolder keyHolder = new GeneratedKeyHolder(); jdbc.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { // 指定主键 PreparedStatement preparedStatement = connection.prepareStatement(sql, new String[]{"id"}); preparedStatement.setString(1, taco.getName()); preparedStatement.setTimestamp(2, new Timestamp(taco.getCreatedAt().getTime())); return preparedStatement; } }, keyHolder); return keyHolder.getKey().longValue(); } private void saveIngredientToTaco(Ingredient ingredient,long tacoId){ jdbc.update("insert into Taco_Ingredients (taco,ingredient) values(?,?)",tacoId,ingredient.getId()); } }
- 主要问题出在表单中的字符串如何转
-
OrderController
- 没什么问题,主要是表单中的数据名字与数据库中的不一致,改下数据库就可以
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 );
代码链接
百度云链接:https://pan.baidu.com/s/1GPXLeZ1SfJ1qyfQuNlaA_Q 密码:7up3
网友评论