springboot、jpa、Thymeleaf使用
环境 :window10 、IDEA 2018.2.4、jdk1.8.0_131、Mysql。
使用springboot框架,mybits作数据处理,Thymeleaf作试图渲染。参考文章 、 项目地址 。
一、创建项目
1、new/create project -> 选择spring initilizr -> next
2、进入dependencies,选择:
左边:web 右边:spring web starter
左边:template 右边:Thymeleaf
左边:SQL 右边:spring data jpa 和 Mysql Driver -> next (可以在建完项目后看看你的pom.xml)
3、选择项目名 和 项目路径,finish (项目文件结构 略)
二、数据库
1、建表 (了解AUTO_INCREMENT=3,未设置key插入时 主键从3开始)
create database boot_demo; use boot_demo; -- ---------------------------- -- Table structure for `tb_area` -- ---------------------------- DROP TABLE IF EXISTS `tb_area`; CREATE TABLE `tb_area` ( `area_id` int(2) NOT NULL AUTO_INCREMENT COMMENT '区域ID', `area_name` varchar(200) DEFAULT NULL COMMENT '区域名称', `priority` int(2) DEFAULT '0' COMMENT '优先级', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `last_edit_time` datetime DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`area_id`), UNIQUE KEY `uk_area` (`area_name`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of tb_area -- ---------------------------- INSERT INTO `tb_area` VALUES ('1', '东苑', '1', null, null); INSERT INTO `tb_area` VALUES ('2', '北苑', '2', null, null);
2、配置application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/boot_demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC spring.datasource.username=root #用户 spring.datasource.password=xu12chuan #密码 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=update spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #jpa下划线与驼峰
spring.thymeleaf.cache=false #不缓存
spring.thymeleaf.mode=LEGACYHTML5 #不严格HTML5文档
spring.mvc.view.prefix=/templates #路径设置(默认值)
3、从数据库表生成实体类 (idea中jpa的这种功能帮我们省去了Entity的编写)
3.1 连接数据库,点击右边DataBase -> + -> DataSource,之后: (可以了解一下生成MySQL控制台)
3.2 添加JPA: File -> Project Structure -> model -> + -> JPA,OK。
3.2 打开Persistence视图,如下操作:
3.4配置生成的 实体类的路径与名称,最后完成发下Entity类中 讨厌的红色波浪线,解决办法。
四、使用JPA
1、Dao中只要继承JpaRepository<>接口就好了,内涵大量的东东。 当然你也可以自定义SQL语句:
public interface AreaRepository extends JpaRepository<TbAreaEntity,Integer> { @Transactional @Modifying //用以update和delete @Query("delete from TbAreaEntity where areaId = ?1") void deleteBy_Id(@Param("areaId") Integer id); @Transactional @Query("select o from TbAreaEntity o where o.areaId=:areaId") TbAreaEntity findBy_id(@Param("areaId") Integer id); //三个areaId要一致。 ?id=1 }
(了解一下Dao的@Param,再回过头来看 类方法写参的注解1@PathParam 和 @PathVariable)
2、创建controller类,先在启动类的同级目录下创建controller包。否则你就要了解一下启动类的@ComponentScan(basePackages = {"com.example.demo.controller"})。
1 package com.example.demo.controller; 2 3 import com.example.demo.dao.AreaRepository; 4 import com.example.demo.entity.TbAreaEntity; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.data.repository.query.Param; 7 import org.springframework.stereotype.Controller; 8 import org.springframework.ui.Model; 9 import org.springframework.validation.BindingResult; 10 import org.springframework.web.bind.annotation.*; 11 12 import javax.validation.Valid; 13 import java.util.Collection; 14 import java.util.HashMap; 15 import java.util.Map; 16 17 @Controller 18 public class AreaController { 19 @Autowired 20 AreaRepository areaSQL; 21 22 @ResponseBody 23 @RequestMapping("/find2") 24 public Map<String,Object> findAll2(){ 25 Map<String,Object> model= new HashMap<String,Object>() ; 26 model.put("areas",areaSQL.findAll()); 27 return model; 28 } 29 @GetMapping("/find3") 30 public String findAll3(Model model) { 31 model.addAttribute("msg","Spring boot and Thymeleaf-->to redit.html"); 32 model.addAttribute("areas", areaSQL.findAll()); 33 return "index"; //在templates中寻找addArea.html,而不会陷入循环 34 } 35 36 @GetMapping("/regit") 37 public String addArea(Model model) { 38 model.addAttribute("area",new TbAreaEntity()); 39 return "regit"; 40 } 41 @RequestMapping(value = "/regit",method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) 42 public String addArea(@Valid TbAreaEntity area, Model model,BindingResult bindingResult){ 43 if (bindingResult.hasErrors()) { // in com..Entity @NotEmpty @Size(min=2, max=30) and @Valid 44 45 return "regit"; //@ModelAttribute Area area --https://www.cnblogs.com/zhangshitong/p/5342076.html 46 }else{ 47 //Map<String,Object> model= new HashMap<String,Object>() ; 48 model.addAttribute("regit","regit success:"+areaSQL.save(area)); 49 areaSQL.save(area);//Model model; 50 return findAll3(model); 51 } 52 } 53 54 @ResponseBody 55 @RequestMapping("/del") //del?id=2 56 public String del(@Param("areaId") Integer id){ 57 areaSQL.deleteBy_Id(id); 58 return areaSQL.existsById(id)?"failed":"success"; 59 } 60 @ResponseBody 61 @RequestMapping("/fin") 62 public Map<String, Object> fin(@Param("areaId") Integer id){ 63 Map<String,Object> model= new HashMap<String,Object>() ; 64 model.put("areas", areaSQL.findBy_id(id)); 65 return model; 66 } 67 }
除了路径无误 还需要类声明@Controller。 (再了解一下类方法传参的注解2 @RequestMapping 、@GetMapping和 @PostMapping)
方法参数Model把值带入了html视图,Map<>就不行。 (@ResponseBody的有无决定方法生成JSON or跳转视图)
3、运行: 可以设置serve.port,默认8080,不是?areaId=1。
两种跳转视图return regit; return ../static/regit.html
动态页面可以th:href=“@{/}”跳转服务器后台程序 然后转另一个动态页面,也可以直接href或src 转static页面。
window.location.href="regit"(服务器),window.location.href="regit.html"(static页面) http://localhost:8080/static/… index.html如下:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" lang="en"> <head> <meta charset="UTF-8"> <title>index</title> <link rel="stylesheet" href="../static/css/table.css"/><!--或者/css/table.css 静态--> </head> <body> <a th:text="'Area:'+${msg}" th:href="@{/regit}">Error</a><!--动态--> <span th:text="${regit}"></span> <table class="gridtable" style="text-align: center"> <tr> <th>AreaId</th><th>AreaName</th><th>priority</th> </tr> <tr th:each="area,areaState : ${areas}"> <td style="border: 1px solid seagreen" th:text="${area.areaId}"></td> <td style="border: 1px solid seagreen" th:text="${area.areaName}"></td> <td style="border: 1px solid seagreen" th:text="${area.priority}"></td> </tr> </table> </body> </html>
table.gridtable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table.gridtable th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #dedede;
}
table.gridtable td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
}
1 <!DOCTYPE html> 2 <html xmlns:th="http://www.thymeleaf.org"><!--引入thymeleaf--> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>添加区域</title></head> 6 <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> 7 <body> 8 <h2 style="color:green;text-align: center;">添加区域</h2> 9 <p th:text="${msg}">你好</p> 10 <form class="form-horizontal" role="form" action="#" th:action="@{/addArea}" th:object="${area}" method="post"> 11 <div class="form-group"> 12 <label for="name" class="col-sm-2 control-label"> 13 区域名称: 14 </label> 15 <div class="col-sm-8"> 16 <input type="text" th:field="*{areaName}" class="form-control" id="areaName" placeholder="输入区域名称"> 17 </div> 18 19 <label class="col-sm-2" style="color:red" th:if="${#fields.hasErrors('areaName')}" th:errors="*{areaName}"> 20 区域名称错误 21 </label> 22 </div> 23 24 <div class="form-group"> 25 <label for="priority" class="col-sm-2 control-label"> 26 优先级 27 </label> 28 29 <div class="col-sm-8"> 30 <input type="text" th:field="*{priority}" class="form-control" id="priority" placeholder="输入优先级"> 31 </div> 32 33 <label class="col-sm-2" style="color:red" th:if="${#fields.hasErrors('priority')}" th:errors="*{priority}"> 34 优先级错误 35 </label> 36 </div> 37 38 <div class="form-group"> 39 <div class="col-sm-12" style="text-align: center"> 40 <button type="submit" class="btn btn-primary" id="btn">Submit</button> 41 <input type="reset" class="btn btn-warning" value="Reset"/> 42 </div> 43 </div> 44 </form> 45 </body> 46 </html> 47 48 addArea.html
运行:
运行中注册数据areaSQL.save(area)时报错:org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():
插入数据时id重复了。 解决:在Entity类@Id后加入 @GeneratedValue(strategy = GenerationType.IDENTITY)
2019-07-18 16:50:59