Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例
<p>这篇文章介绍如何使用 Jpa 和 Thymeleaf 做一个增删改查的示例。</p>
先和大家聊聊我为什么喜欢写这种脚手架的项目,在我学习一门新技术的时候,总是想快速的搭建起一个 Demo 来试试它的效果,越简单越容易上手最好。在网上找相关资料的时候总是很麻烦,有的文章写的挺不错的但是没有源代码,有的有源代码但是文章介绍又不是很清楚,所在找资料的时候稍微有点费劲。因此在我学习 Spring Boot 的时候,会写一些最简单基本的示例项目,一方面方便其它朋友以最快的方式去了解,一方面如果我的项目需要用到相关技术的时候,直接在这个示例版本去改造或者集成就可以。
现在的技术博客有很多的流派,有的喜欢分析源码,有的倾向于底层原理,我最喜欢写这种小而美的示例,方便自己方便他人。
其实以前写过 Thymeleaf 和 Jpa 的相关文章: Spring Boot (四): Thymeleaf 使用详解和Spring Boot(五):Spring Data Jpa 的使用 里面的代码示例都给的云收藏的内容Favorites-web,云收藏的内容比较多,查找起来不是很方便,因此想重新整理一篇快速上手、简单的内容,来介绍 Jpa 和 Thymeleaf 的使用,也就是本文的内容。
这篇文章就不在介绍什么是 Jpa 、 Thymeleaf ,如果还不了解这些基本的概念,可以先移步前两篇相关文章。
快速上手
配置文件
pom 包配置
pom 包里面添加 Jpa 和 Thymeleaf 的相关包引用
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
在application.properties中添加配置
spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
spring.thymeleaf.cache=false
其中propertiesspring.thymeleaf.cache=false
是关闭 Thymeleaf 的缓存,不然在开发过程中修改页面不会立刻生效需要重启,生产可配置为 true。
在项目 resources 目录下会有两个文件夹:static目录用于放置网站的静态内容如 css、js、图片;templates 目录用于放置项目使用的页面模板。
启动类
启动类需要添加 Servlet 的支持
@SpringBootApplication
public class JpaThymeleafApplication extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(JpaThymeleafApplication.class);}
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span><span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">JpaThymeleafApplication</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
<span class="o">}</span>
}
数据库层代码
实体类映射数据库表
@Entity
public class User {@Id@GeneratedValueprivate long id;@Column(nullable = false, unique = true)private String userName;@Column(nullable = false)private String password;@Column(nullable = false)private int age;...
}
继承 JpaRepository 类会自动实现很多内置的方法,包括增删改查。也可以根据方法名来自动生成相关 Sql,具体可以参考: Spring Boot (五):Spring Data Jpa 的使用
public interface UserRepository extends JpaRepository<User, Long> {User findById(long id);Long deleteById(Long id);
}
业务层处理
Service 调用 Jpa 实现相关的增删改查,实际项目中 Service 层处理具体的业务代码。
@Service
public class UserServiceImpl implements UserService{
<span class="nd">@Autowired</span>
<span class="kd">private</span> <span class="nc">UserRepository</span> <span class="n">userRepository</span><span class="o">;</span><span class="nd">@Override</span>
<span class="kd">public</span> <span class="nc">List</span><span class="o"><</span><span class="nc">User</span><span class="o">></span> <span class="nf">getUserList</span><span class="o">()</span> <span class="o">{</span><span class="k">return</span> <span class="n">userRepository</span><span class="o">.</span><span class="na">findAll</span><span class="o">();</span>
<span class="o">}</span><span class="nd">@Override</span>
<span class="kd">public</span> <span class="nc">User</span> <span class="nf">findUserById</span><span class="o">(</span><span class="kt">long</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span><span class="k">return</span> <span class="n">userRepository</span><span class="o">.</span><span class="na">findById</span><span class="o">(</span><span class="n">id</span><span class="o">);</span>
<span class="o">}</span><span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">save</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span><span class="n">userRepository</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
<span class="o">}</span><span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">edit</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span><span class="n">userRepository</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
<span class="o">}</span><span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">delete</span><span class="o">(</span><span class="kt">long</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span><span class="n">userRepository</span><span class="o">.</span><span class="na">delete</span><span class="o">(</span><span class="n">id</span><span class="o">);</span>
<span class="o">}</span>
}
Controller 负责接收请求,处理完后将页面内容返回给前端。
@Controller
public class UserController {
<span class="nd">@Resource</span>
<span class="nc">UserService</span> <span class="n">userService</span><span class="o">;</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">index</span><span class="o">()</span> <span class="o">{</span><span class="k">return</span> <span class="s">"redirect:/list"</span><span class="o">;</span>
<span class="o">}</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/list"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">list</span><span class="o">(</span><span class="nc">Model</span> <span class="n">model</span><span class="o">)</span> <span class="o">{</span><span class="nc">List</span><span class="o"><</span><span class="nc">User</span><span class="o">></span> <span class="n">users</span><span class="o">=</span><span class="n">userService</span><span class="o">.</span><span class="na">getUserList</span><span class="o">();</span><span class="n">model</span><span class="o">.</span><span class="na">addAttribute</span><span class="o">(</span><span class="s">"users"</span><span class="o">,</span> <span class="n">users</span><span class="o">);</span><span class="k">return</span> <span class="s">"user/list"</span><span class="o">;</span>
<span class="o">}</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/toAdd"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">toAdd</span><span class="o">()</span> <span class="o">{</span><span class="k">return</span> <span class="s">"user/userAdd"</span><span class="o">;</span>
<span class="o">}</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/add"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">add</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span><span class="n">userService</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">user</span><span class="o">);</span><span class="k">return</span> <span class="s">"redirect:/list"</span><span class="o">;</span>
<span class="o">}</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/toEdit"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">toEdit</span><span class="o">(</span><span class="nc">Model</span> <span class="n">model</span><span class="o">,</span><span class="nc">Long</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span><span class="nc">User</span> <span class="n">user</span><span class="o">=</span><span class="n">userService</span><span class="o">.</span><span class="na">findUserById</span><span class="o">(</span><span class="n">id</span><span class="o">);</span><span class="n">model</span><span class="o">.</span><span class="na">addAttribute</span><span class="o">(</span><span class="s">"user"</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span><span class="k">return</span> <span class="s">"user/userEdit"</span><span class="o">;</span>
<span class="o">}</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/edit"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">edit</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span><span class="n">userService</span><span class="o">.</span><span class="na">edit</span><span class="o">(</span><span class="n">user</span><span class="o">);</span><span class="k">return</span> <span class="s">"redirect:/list"</span><span class="o">;</span>
<span class="o">}</span><span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/delete"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">delete</span><span class="o">(</span><span class="nc">Long</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span><span class="n">userService</span><span class="o">.</span><span class="na">delete</span><span class="o">(</span><span class="n">id</span><span class="o">);</span><span class="k">return</span> <span class="s">"redirect:/list"</span><span class="o">;</span>
<span class="o">}</span>
}
return "user/userEdit";
代表会直接去 resources 目录下找相关的文件。return "redirect:/list";
代表转发到对应的 Controller,这个示例就相当于删除内容之后自动调整到 list 请求,然后再输出到页面。
页面内容
list 列表
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"/><title>userList</title><link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
</head>
<body class="container">
<br/>
<h1>用户列表</h1>
<br/><br/>
<div class="with:80%"><table class="table table-hover"><thead><tr><th>#</th><th>User Name</th><th>Password</th><th>Age</th><th>Edit</th><th>Delete</th></tr></thead><tbody><tr th:each="user : ${users}"><th scope="row" th:text="${user.id}">1</th><td th:text="${user.userName}">neo</td><td th:text="${user.password}">Otto</td><td th:text="${user.age}">6</td><td><a th:href="@{/toEdit(id=${user.id})}">edit</a></td><td><a th:href="@{/delete(id=${user.id})}">delete</a></td></tr></tbody></table>
</div>
<div class="form-group"><div class="col-sm-2 control-label"><a href="/toAdd" th:href="@{/toAdd}" class="btn btn-info">add</a></div>
</div>
</body>
</html>
效果图:
<tr th:each="user : ${users}">
这里会从 Controler 层 model set 的对象去获取相关的内容,th:each
表示会循环遍历对象内容。
其实还有其它的写法,具体的语法内容可以参考这篇文章: Spring Boot (四): Thymeleaf 使用详解
修改页面:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"/><title>user</title><link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
</head>
<body class="container">
<br/>
<h1>修改用户</h1>
<br/><br/>
<div class="with:80%"><form class="form-horizontal" th:action="@{/edit}" th:object="${user}" method="post"><input type="hidden" name="id" th:value="*{id}" /><div class="form-group"><label for="userName" class="col-sm-2 control-label">userName</label><div class="col-sm-10"><input type="text" class="form-control" name="userName" id="userName" th:value="*{userName}" placeholder="userName"/></div></div><div class="form-group"><label for="password" class="col-sm-2 control-label" >Password</label><div class="col-sm-10"><input type="password" class="form-control" name="password" id="password" th:value="*{password}" placeholder="Password"/></div></div><div class="form-group"><label for="age" class="col-sm-2 control-label">age</label><div class="col-sm-10"><input type="text" class="form-control" name="age" id="age" th:value="*{age}" placeholder="age"/></div></div><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><input type="submit" value="Submit" class="btn btn-info" /> <a href="/toAdd" th:href="@{/list}" class="btn btn-info">Back</a></div>
<span class="nt"></div></span>
<span class="nt"></form></span>
</div>
</body>
</html>
添加页面和修改类似就不在贴代码了。
效果图:
这样一个使用 Jpa 和 Thymeleaf 的增删改查示例就完成了。
文章内容已经升级到 Spring Boot 2.x
当然所以的示例代码都在这里:
示例代码-github
示例代码-码云
<div>
<img src="http://favorites.ren/assets/images/java.jpg"><br>微信扫描二维码,关注我的公众号
(转载本站文章请注明作者和出处 纯洁的微笑-ityouknow)
点击了解:全网唯二以程序员为主题的漫画公众号
<!-- Comments --><div class="comment"><a href="#" class="show_disqus_comment" onclick="return false;">Show Disqus Comments</a>
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {this.page.url = 'http://www.ityouknow.com/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html';this.page.identifier = '/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html';this.page.title = 'Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例';
};
var disqus_loaded = false;
$(function() {$('.show_disqus_comment').on('click', function() { // DON'T EDIT BELOW THIS LINE$(this).html('加载中...');var that = this;if (!disqus_loaded) {var d = document, s = d.createElement('script');s.type = 'text/javascript';s.async = true;var shortname = 'ityouknow';s.src = '//' + shortname + '.disqus.com/embed.js';s.setAttribute('data-timestamp', +new Date());(d.head || d.body).appendChild(s);disqus_loaded = true;}$(that).remove();})
})
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript><div id="gitalk-container"><div class="gt-container"><div class="gt-meta"><span class="gt-counts"><a class="gt-link gt-link-counts" href="https://github.com/ityouknow/blog-comments/issues/81" target="_blank">23</a> 条评论</span><div class="gt-user"><div class="gt-user-inner"><span class="gt-user-name">未登录用户</span><span class="gt-ico gt-ico-arrdown"><span class="gt-svg"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" p-id="1619"><path d="M511.872 676.8c-0.003 0-0.006 0-0.008 0-9.137 0-17.379-3.829-23.21-9.97l-251.277-265.614c-5.415-5.72-8.743-13.464-8.744-21.984 0-17.678 14.33-32.008 32.008-32.008 9.157 0 17.416 3.845 23.25 10.009l228.045 241.103 228.224-241.088c5.855-6.165 14.113-10.001 23.266-10.001 8.516 0 16.256 3.32 21.998 8.736 12.784 12.145 13.36 32.434 1.264 45.233l-251.52 265.6c-5.844 6.155-14.086 9.984-23.223 9.984-0.025 0-0.051 0-0.076 0z" p-id="1620"></path></svg></span></span></div></div></div><div class="gt-header"><a class="gt-avatar-github"><span class="gt-ico gt-ico-github"><span class="gt-svg"><svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
@lizhenzhaofirst
现在的技术博客有很多的流派,有的喜欢分析源码,有的倾向于底层原理,我最喜欢写这种小而美的示例,方便自己方便他人。<=>水陆草木之花,可爱者甚蕃。晋陶渊明独爱菊。自李唐来,世人甚爱牡丹。予独爱莲之出淤泥而不染,濯清涟而不妖,中通外直,不蔓不枝,香远益清,亭亭净植,可远观而不可亵玩焉。。。。。。。语法何其相似。嗯,一个伟大的发现。哈哈
果真其实大部分的程序员都是很有趣的,很有文采的,哈哈。顺带把自己也夸了
@Umizhangs
大佬,上面在写UserRepository接口时里面的“Long deleteById(Long id);”一直报错怎么解决?提示说:无效的源查询,实体类中没有这个属性
因为 作者可能写错了。继承了JpaRepository后。UserRepository里不用写任何东西。默认都有增save删delete改save查findxxxx的方法。删除的方法名是delete(xxxxx)。如果你要写就要遵守jpa命名规范。命名规范基本都是针对查询的。只用过findById。你这个deleteById还是头一次见。应该是不符合jpa命名规则。无法给你自动生成SQL。你要是还想用这个方法名的话deleteById。那你就在上边加@query("delete from XXXXX where id= :myId")
deleteById(@param("myId") long myId); 这样写。
Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract void com.example.springboot.dao.UserRepository.delete(long)! No property delete found for type User!
@ityouknow 请教一个问题,在user实体类去掉age不能为空的约束后,增加用户的时候如果不填年龄会报如下错误:nested exception is java.lang.NumberFormatException: For input string: "";也就是说不填年龄的时候会报空字符串转int的错误,请问这种情况该如何处理呢?谢谢
你既然去掉了age的非空约束。是不是应该更新一下表?让表里age可以为空。你这个问题证明age是int数字类型。你为啥还要传个Sting类型的空字符?不传参数或者传null不好么?
表里的非空约束自然是去掉了。age的传参如何控制?
…
@ityouknow 请教一个问题,在user实体类去掉age不能为空的约束后,增加用户的时候如果不填年龄会报如下错误:nested exception is java.lang.NumberFormatException: For input string: “”;也就是说不填年龄的时候会报空字符串转int的错误,请问这种情况该如何处理呢?谢谢
你既然去掉了age的非空约束。是不是应该更新一下表?让表里age可以为空。你这个问题证明age是int数字类型。你为啥还要传个Sting类型的空字符?不传参数或者传null不好么?
表里的非空约束自然是去掉了。age的传参如何控制?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
</div></div>
Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例相关推荐
- (转)Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例
http://www.ityouknow.com/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html 这篇文章介绍如何使用 Jpa 和 ...
- SpringBoot集成thymeleaf增删改查示例
有小伙伴找我要个 thymeleaf 的 demo,说自己集成的总是报错,所以就有了这篇- 关于什么是 thymeleaf 我就不赘述了,相信搜到这篇的大部分是奔着如何集成来的. 本文源码先附上:ht ...
- JavaScript学习(四十八)—原型对象的增删改查
JavaScript学习(四十八)-原型对象的增删改查 一.构造方法与原型对象的图解 二.型对象的增删改查 (一).什么是原型 每个函数都会有一个属性--prototype属性,这个属性都会有一个对象 ...
- java从入门到精通二十四(三层架构完成增删改查)
java从入门到精通二十四(三层架构完成增删改查) 前言 环境准备 创建web项目结构 导入依赖和配置文件 创建层次模型 实现查询 实现添加 实现修改 完成删除 做一个用户登录验证 会话技术 cook ...
- spring boot(十五)spring boot+thymeleaf+jpa增删改查示例
快速上手 配置文件 pom包配置 pom包里面添加jpa和thymeleaf的相关包引用 <dependency><groupId>org.springframework.bo ...
- Spring Boot 学习[四] web项目实战训练(增删改查,分页,排序)
Spring boot非常适合Web应用程序开发.您可以轻松创建自包含的HTTP应用.web服务器采用嵌入式Tomcat,或者Jetty等. 几点说明: Spring boot开发web项目,通常打成 ...
- boot spring 接口接收数据_基于 Spring Boot 实现 Restful 风格接口,实现增删改查功能...
优质文章,及时送达 Spring Boot介绍 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配 ...
- Spring Date JPA实现增删改查
1.新建一个Cart类 package com.entity;public class Cart {private int id;private int userId;private int medi ...
- Spring JPA实现增删改查
1. 创建一个Spring工程 2.配置application文件 spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver spri ...
最新文章
- Nature Protocols:整合宏基因组、代谢组和表型分析的的计算框架
- Codeforces 825E - Minimal Labels
- jvm系列(九):如何优化Java GC「译
- sqlyog表添加列_如何用数据透视表求差,而不是求和?
- 2017年最新的全国省市sql数据
- Parallels Desktop 17 亮点整理,7 大改进与变化
- 开环增益对负反馈放大电路的影响
- mysql 通达信公式_公式选股--均线黏合(更多公式关注公众号“斯达克逻辑”)...
- 程序员必备英语单词清单
- 系统学习编程笔记(十二)
- python json dump时,中文乱码问题
- linux 系统命令被后门修改_一次Linux系统被攻击的分析过程
- JS 函数的递归算法
- <Android开发> Android vold - 第三篇 vold 的NetLinkManager类简介
- dataTable 查询,重置
- 华硕EeePC: 没有光驱重装系统(用U盘作为电脑启动盘)
- 网络支付结算{网银、第三方支付、超级网银}
- 对泛型上下限(协变,逆变)理解的拙见
- 五、资产证券化的加速
- oracle 与赛门铁克,赛门铁克Oracle启动Veritas数据中心认证