项目已上传:https://codechina.csdn.net/qq_36286039/javaee
注意本项目是包含后文JPA 查询用法内容的,若您想看只有本文内容的项目,请下载:
https://download.csdn.net/download/qq_36286039/21941623?spm=1001.2014.3001.5501
先看下效果:
id是自动生成的,跳数了是因为之前删过数据
删除后
一些术语、概念
entity-dao-service-web层
准备工作
- 新建 Spring Boot 项目:jpademo2
- MySQL数据库:还是testdb user表
- 添加相关依赖:
- pom.xml
<!-- Spring Data JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- jquery-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
<!-- bootstrap-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<!-- bootstrap-datetimepicker -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>Eonasdan-bootstrap-datetimepicker</artifactId>
<version>4.17.47</version>
</dependency>
<!-- webjars-locator版本控制 -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.31</version>
</dependency>
<!-- lombok -->
<!--Lombok插件(神器),能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString…等方法。 这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
不仅要添加 Lombok 依赖,idea 还要安装 Lombok 插件
安装 Lombok 插件方法:
Lombok 插件需要开启 Enable Annotation Processing
- application.properties
#自动生成数据库表(关键)
spring.jpa.hibernate.ddl-auto=update
#mysql数据库连接配置(非常重要)
spring.datasource.url = jdbc:mysql://localhost:3306/testdb?serverTimezone=Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = root
#mysql数据库驱动程序(重要)
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
#jpa配置:在控制台显示Hibernate的sql(可选)
spring.jpa.show-sql = true
#其他配置:关闭Thymeleaf 的缓存
spring.thymeleaf.cache = false
项目实践
- 创建实体类
- 在新建 entity 包中新建 User 类:映射数据库表
user.java
package com.example.jpademo2.entity;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Entity //声明类为实体类,不能掉!
@Data//lombok注解
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false,unique = true,length = 20)
private String username;
@Column(nullable = false,length = 20)
private String password;
@Column(nullable = false)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date regdate;
@Column(nullable = false)
private int status;
//getter/setter真的不需要了,因为你安装了Lombok~~~
}
- 创建数据接口访问层(Repository仓库)
- 在新建 repository 包中新建 UserRepository 接口。
- Repository 接口要继承 JpaRepository<User, Long> 接口。
package com.example.jpademo2.repository;
import com.example.jpademo2.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,Long> {
// JpaRepository 自动实现了很多内置的CURD方法
// 可直接调用而不用自己写代码,例如:
// List<T> findAll();
// Optional<T> findById(id);
// User save(user);
// void delete(user);
// void deleteById(id);
// long count();
// boolean existsById(id);
}
- 创建服务层接口
- 在新建 service 包中新建 UserService 接口。
- UserService 接口中声明业务相关方法(根据业务需要)。
package com.example.jpademo2.service;
import com.example.jpademo2.entity.User;
import java.util.List;
//服务层接口
public interface UserService {
//根据也无需要定义业务功能接口方法
public List<User> getUserList();
public User findUserById(Long id);
public void save(User user);
public void edit(User user);
public void delete(Long id);
}
- 实现服务层接口
- 在 service 包中新建 UserServiceImp 类(实现UserService接口)。
- 服务实现类调用 UserRepository 实现具体业务。
这段代码里注意不要掉了@Service
package com.example.jpademo2.service;
import com.example.jpademo2.entity.User;
import com.example.jpademo2.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
//实现服务层接口
@Service
public class UserServiceImp implements UserService{
@Autowired
private UserRepository userRepository;
@Override
public List<User> getUserList(){
return userRepository.findAll();//直接调用Repository内置的CURD方法
}
@Override
public User findUserById(Long id){
return userRepository.findById(id).get();//直接调用Repository内置的CURD方法
//findById(id)返回的是Optional类(一个可以为null的容器对象)
//如果Optional容器中存在对象,则调用get()方法返回该对象
}
@Override
public void edit(User user){
userRepository.save(user);//直接调用Repository内置的CURD方法
}
@Override
public void save(User user){
userRepository.save(user);//直接调用Repository内置的CURD方法
}
@Override
public void delete(Long id){
userRepository.deleteById(id);//直接调用Repository内置的CURD方法
}
}
- 调用服务层完成业务控制
- 在新建 controller 包中新建 UserController 控制器。
- 上面的
@Service
要是掉了,这里会报错的
package com.example.jpademo2.controller;
import com.example.jpademo2.entity.User;
import com.example.jpademo2.service.UserService;
import com.example.jpademo2.service.UserServiceImp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Controller
public class UserController {
@Autowired // 自动注入( 无需自己new对象:UserService userService=new UserServiceImp(); )
private UserService userService;
@RequestMapping("/")
public String index() {
return "redirect:/list"; //请求转发到 /list
}
@RequestMapping("/list")
public String list(Model model) {
List<User> users = userService.getUserList();
model.addAttribute("users", users);
return "user/list";
}
@RequestMapping("/add")
public String add() {
return "user/add"; //打开创建user界面
}
@PostMapping("/add")
public String add(User user) {
//保存新创建的user
user.setRegdate(new Date());
user.setStatus(0);
userService.save(user);
return "redirect:/list";
}
@RequestMapping("/edit/{id}")
public String edit(Model model, @PathVariable Long id) {
User user=userService.findUserById(id);
model.addAttribute("user", user);
return "user/edit"; //打开编辑user界面
}
@PostMapping("/edit")
public String edit(User user) {
//保存编辑好的user
userService.edit(user);
return "redirect:/list";
}
@RequestMapping("/delete/{id}")
public String delete(Model model,@PathVariable Long id) {
User user=userService.findUserById(id);
model.addAttribute("user", user);
return "user/delete"; //删除之前道个别(看看数据)
}
@PostMapping("/delete/{id}")
public String delete(@PathVariable Long id) {
//确认删除
userService.delete(id);
return "redirect:/list";
}
}
- 视图层:
- 在 templates 中新建 user 文件夹,添加相关页面文件。
list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
<link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
<div class="container">
<h2>用户列表</h2>
<div class="with:80%">
<div style="margin: 20px;">
<a href="/add" th:href="@{/add}" class="btn btn-info">添加用户</a>
</div>
<table class="table table-hover">
<tr>
<th>用户id</th>
<th>用户名</th>
<th>密码</th>
<th>创建时间</th>
<th>用户状态</th>
<th>操作</th>
<th>操作</th>
</tr>
<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}">123456</td>
<td th:text="${#dates.format(user.regdate,'yyyy/MM/dd HH:mm:ss')}">2020/11/11</td>
<td th:text="${user.status}">0</td>
<td><a th:href="@{/edit/{id}(id=${user.id})}">编辑</a></td>
<td><a th:href="@{/delete/{id}(id=${user.id})}">删除</a></td>
</tr>
</table>
</div>
</div>
</body>
</html>
add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
<link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
<div class="container">
<h3 class="col-sm-offset-1">添加用户</h3>
<div>
<form class="form-horizontal" th:action="@{/add}" method="post">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="username" id="username" placeholder="用户名"/>
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码</label>
<div class="col-sm-6">
<input type="password" class="form-control" name="password" id="password" placeholder="密码"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-6">
<input type="submit" value="保存" class="btn btn-info"/>
<input type="reset" value="重填" class="btn btn-info col-sm-offset-1"/>
<a th:href="@{/list}" class="btn btn-info col-sm-offset-1">返回</a>
</div>
</div>
</form>
</div>
</div>
</body>
</html>
delete.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
<link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
<div class="container">
<h3 class="col-sm-offset-1">确认删除用户</h3>
<div>
<form class="form-horizontal" th:action="@{/delete/{id}(id=${user.id})}" th:object="${user}" method="post">
<input type="hidden" name="id" th:value="*{id}"/> <!--id值隐藏不修改-->
<div class="form-group">
<label class="col-sm-2 control-label">编号</label>
<div class="col-sm-6">
<label class="control-label" th:text="*{id}">id</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">用户名</label>
<div class="col-sm-6">
<label class="control-label" th:text="*{username}">username</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">密码</label>
<div class="col-sm-6">
<label class="control-label" th:text="*{password}">password</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">注册日期</label>
<div class="col-sm-6">
<label class="control-label" th:text="*{#dates.format(regdate,'yyyy-MM-dd HH:mm:ss')}">regdate</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">状态</label>
<div class="col-sm-6">
<label class="control-label" th:text="*{status}">status</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-6">
<input type="submit" value="确认删除" class="btn btn-info"/>
<a href="/list" th:href="@{/list}" class="btn btn-info col-sm-offset-1">返回</a>
</div>
</div>
</form>
</div>
</div>
</body>
</html>
edit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>user</title>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
<link th:href="@{/webjars/bootstrap/css/bootstrap.min.css}" rel="stylesheet">
<script th:src="@{/webjars/momentjs/min/moment-with-locales.js}"></script>
<link th:href="@{/webjars/Eonasdan-bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css}" rel="stylesheet">
<script th:src="@{/webjars/Eonasdan-bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js}"></script>
</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}"/> <!--id值隐藏不修改,编辑时必须带上id值-->
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="username" id="username" th:value="*{username}" placeholder="用户名"/>
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="password" id="password" th:value="*{password}" placeholder="密码"/>
</div>
</div>
<!--日历时间框-->
<div class="form-group">
<label for="regdate" class="col-sm-2 control-label">注册日期</label>
<div class="col-sm-6">
<div class="input-group" id='datetimepicker'>
<input type='text' class="form-control" id="regdate" name="regdate"/>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<div class="form-group">
<label for="status" class="col-sm-2 control-label">用户状态</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="status" id="status" th:value="*{status}" placeholder="用户状态"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-6">
<input type="submit" value="保存" class="btn btn-info"/>
<a href="/list" th:href="@{/list}" class="btn btn-info col-sm-offset-1">返回</a>
</div>
</div>
</form>
</div>
<script th:inline="javascript"> $(function () {
$('#datetimepicker').datetimepicker({
format: 'YYYY-MM-DD HH:mm:ss', //HH是24小时制,hh是12小时制 locale: moment.locale('zh-cn'), //中文日历 defaultDate: /*[[${user.regdate}]]*/"1990-1-1" }); }); </script>
</body>
</html>
至此,你已经可以运行了,访问localhost:8080/list
试试吧!