项目已上传: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

项目实践

  1. 创建实体类
  • 在新建 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~~~
}

  1. 创建数据接口访问层(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);
}

  1. 创建服务层接口
  • 在新建 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);
}

  1. 实现服务层接口
  • 在 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方法
    }
}
  1. 调用服务层完成业务控制
  • 在新建 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";
    }

}

  1. 视图层:
  • 在 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试试吧!