最新SpringBoot2.0X整合SpringData JPA实战完整篇
先来张效果图吧
一、pom.xml 导入依赖包
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--jpa依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--devtools热部署--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional><scope>true</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies>
二、application.yml 配置
spring:datasource:url: jdbc:mysql://localhost:3306/db_itboot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverjpa:hibernate:ddl-auto: updateshow-sql: truethymeleaf:prefix: classpath:/templates/suffix: .htmlmode: HTMLencoding: UTF-8servlet:content-type: text/htmlcache: falseresources:chain:strategy:content:enabled: falsepaths: /**mvc:static-path-pattern: /static/**
server:port: 8081
三、User 实体类
@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "user") //@Table指定和哪个表对应,如果省略该注解默认表名就是user
public class User {@Id //这是一个主键@GeneratedValue(strategy = GenerationType.IDENTITY) //自增主键@Column(name = "id", unique = true, length = 11) //unique = true 是指这个字段的值在这张表里不能重复,所有记录值都要唯一,就像主键那样;private Integer id;@Column(nullable=false,name = "name") //省略默认列名就是属性名、nullable=false是这个字段在保存时必需有值,不能还是null值就调用save去保存入库;private String name;@Column(nullable=true,name = "sex") //nullable默认可以为空,如果改为false,参数没有值的时候就save会报错private Integer sex;private String position;...此处省略get、set方法//无参数的构造器public User() {}//添加信息:有参数的构造器public User(String name){this.name = name;}//更新信息:有参数的构造器public User(Integer id,String name){this.id = id;this.name = name;}
}
四、控制器、实现层核心接口编写
包结构如下:
UserDao.java
//继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法
public interface UserDao extends JpaRepository<User,Integer> {}
五、测试代码接口
UserController.java
@Autowiredprivate UserDao userDao;/**** 根据id查询用户信息* @param id* @return*/@GetMapping(value = "getById/{id}")@ResponseBodypublic User getUser(@PathVariable("id") Integer id){Optional<User> user = userDao.findById(id); //根据ID查询return user.ofNullable(user).map(user1->user.get()).orElse(null);}/**** 查询所有用户List集合* @return*/@GetMapping(value = "list")@ResponseBodypublic List<User> findAll(){return userDao.findAll();}/*** 添加用户信息* @return*/@PostMapping(value = "save")@ResponseBodypublic Map<String,Object> saveUser(){Map<String,Object> map = new HashMap<>();User user = userDao.save(new User("DT开发者002"));if (!StringUtils.isEmpty(user)){map.put("code",2000);map.put("message","添加成功");map.put("data",user);}else {map.put("code",20001);map.put("message","添加失败");}return map;}/**** 根据id修改用户信息* @return*/@PostMapping(value = "update/{id}")@ResponseBodypublic Map<String,Object> updateUserById(@PathVariable Integer id){Map<String,Object> map = new HashMap<>();//1、根据id查询用户信息Optional<User> user = userDao.findById(id);if(user.isPresent()){//2、调用接口进行更新User update = userDao.save(new User(user.get().getId(), "DT开发者0022"));//3、判断是否成功if(!StringUtils.isEmpty(update)){map.put("code",2000);map.put("message","修改成功");map.put("data",user);}else {map.put("code",2001);map.put("message","事务回滚");map.put("data",user);}System.out.println("ID==="+user.get().getId());}else {map.put("code",2001);map.put("message","修改失败");map.put("data",user);}return map;}/***根据主键id删除用户信息* @return*/@DeleteMapping(value = "remove/{id}")@ResponseBodypublic Map<String,Object> removeUserById(@PathVariable Integer id){Map<String,Object> map = new HashMap<>();userDao.deleteById(id);map.put("code",2000);map.put("message","删除成功");map.put("data",id);return map;}
自定义CRUD、UserController.java
/*** 自定义:根据用户名查询用户信息* @param name* @return*/@GetMapping(value = "findCustomByName")@ResponseBodypublic User findCustomByName(@PathParam("name") String name){return userService.findCustomByName(name);}/*** 自定义:根据用户名查询用户信息 (模糊查询)* @param name* @return*/@GetMapping(value = "findVagueByName")@ResponseBodypublic List<User> findVagueByName(@PathParam("name") String name){return userService.findVagueByName(name);}/*** 自定义:根据用户名id更新用户信息* @param user* @return*/@PostMapping(value = "updateCustomByById")@ResponseBodypublic Map<String,Object> updateCustomByById(User user){return userService.updateCustomByById(user);}/*** 自定义:根据用户名id删除用户信息* @param id* @return*/@DeleteMapping(value = "removeCustomByById/{id}")@ResponseBodypublic Map<String,Object> removeCustomByById(@PathVariable Integer id){return userService.removeCustomByById(id);}
UserServiceImpl .java
@Service
public class UserServiceImpl implements UserService {@Resourceprivate UserDao userDao;/*** 自定义:根据用户名查询用户信息* @param name* @return*/@Overridepublic User findCustomByName(String name) {if(StringUtils.isNotBlank(name)){return userDao.findCustomByName(name);}else {return null;}}/*** 自定义:根据用户名查询用户信息 (模糊查询)* @param name* @return*/@Overridepublic List<User> findVagueByName(String name) {if(StringUtils.isNotBlank(name)){return userDao.findVagueByName(name);}else {return null;}}/*** 自定义:根据用户名id更新用户信息* @param user* @return*/@Override@Transactional //必须加@Transactional,来代表这是一个事务级别的操作。jpa要求,'没有事务支持,不能执行更新和删除操作'public Map<String, Object> updateCustomByById(User user) {Map<String,Object> map = new HashMap<>();if(user !=null){//注意:1、返回值只有int和void 2、入参绝对不能定义成 User对象,JPA不支持,只有查询可以使用SPEL表达式int user1 = userDao.updateCustomByById(user.getId(),user.getName());if(user1 > 0){map.put("code","2000");map.put("message","修改成功");map.put("data",user1);}else {map.put("code","2001");map.put("message","修改失败");}}else {map.put("code","2001");map.put("message","参数不能为空");}return map;}/*** 自定义:根据用户名id删除用户信息* @param id* @return*/@Override@Transactionalpublic Map<String, Object> removeCustomByById(Integer id) {Map<String,Object> map = new HashMap<>();int count = userDao.removeCustomByById(id);if(count > 0){map.put("code","2000");map.put("message","删除成功");map.put("data",id);}else {map.put("code","2001");map.put("message","删除失败");}return map;}
}
UserDao.java
public interface UserDao extends JpaRepository<User,Integer> {/*** 自定义:根据用户名查询用户信息* @param name* @return*/@Query(value = "select id,name from user where name = :name",nativeQuery = true)User findCustomByName(@Param("name") String name);/*** 自定义:根据用户名查询用户信息 (模糊查询)* @param name* @return*///@Query(value = "select id,name from user where name like %:name%",nativeQuery = true) //第一种写法@Query(value = "select t.id,t.name from user t where t.name like %?1%",nativeQuery = true) //第二种写法 1表示占位符,从第一个参数开始List<User> findVagueByName(String name);/*** 自定义:根据用户名id更新用户信息* @param id* @param name* @return*/@Modifying@Query(value = "update user set name = :name where id = :id",nativeQuery = true)int updateCustomByById(Integer id,String name); //入参绝对不能定义成 User对象,JPA不支持,只有查询可以使用SPEL表达式/*** 自定义:根据用户名id删除用户信息* 执行完modifying query, EntityManager可能会包含过时的数据,因为EntityManager不会自动清除实体。* 只有添加clearAutomatically属性,EntityManager才会自动清除实体对象。* @param id* @return*/@Modifying(clearAutomatically = true)@Query(value = "delete from user where id = :id",nativeQuery = true)int removeCustomByById(Integer id);
}
六、JPA + BootStrap 无条件查询分页
UserController.java
/*** 分页(无条件查询)* @param modelMap* @param pageNumber* @param pageSize* @return*/
@GetMapping(value = "listUsers")
public String listUsers(ModelMap modelMap,@RequestParam(value = "pageNumber",defaultValue = "0") Integer pageNumber,@RequestParam(value = "pageSize",defaultValue = "5") Integer pageSize){//设置分页Pageable pageable = PageRequest.of(pageNumber,pageSize, Sort.Direction.DESC, "id");//进行查询Page<User> userPage = userDao.findAll(pageable);modelMap.addAttribute("data",userPage);return "index";
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"layout:decorator="page">
<head><meta charset="UTF-8"><title>分页</title><script src="https://cdn.bootcdn.net/ajax/libs/jquery/2.2.4/jquery.min.js"></script><!-- 最新的 Bootstrap 核心 JavaScript 文件 --><script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script><!-- 最新版本的 Bootstrap 核心 CSS 文件 --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" ><style>.active{background: #49af4f !important;color: #fff !important;}</style>
</head>
<body style="padding: 50px;">
<div class="panel panel-success"><div class="panel-heading"><h2 class="panel-title" style="text-align: center;font-weight: bold;">无条件查询 | 分页</h2></div><div class="panel-body"><!--bootstrap表格--><table class="table table-hover"><thead><tr><th>ID</th><th>用户</th><th>性别</th><th>职位</th></tr></thead><tbody><tr th:each="user : ${data}"><td th:text="${user.id}"></td><td th:text="${user.name}"></td><td th:text="${user.sex == 1 ? '女':'男'}"></td><td th:text="${user.position}">2</td></tr></tbody></table><!--bootstrap自定义分页--><ul class="pager"><li th:if="${data.hasPrevious()}"><a th:href="@{/user/listUsers(pageNumber=0)}">首页</a></li><li th:if="${data.hasPrevious()}"><a th:href="@{/user/listUsers(pageNumber=${data.number}-1)}">上一页</a></li><!--总页数大于等于0并且小于等于5--><div th:if="${(data.totalPages le 5) and (data.totalPages gt 0)}" th:remove="tag"><!--根据一个数字在页面循环生成固定的标签--><div th:each="pg : ${#numbers.sequence(0, data.totalPages - 1)}" th:remove="tag"><!--如果循环的数等于当前页--><span th:if="${pg eq data.getNumber()}" th:remove="tag"><li><span class="active" th:text="${pg+1}"></span></li></span><!--如果循环的数不等于当前页--><span th:unless="${pg eq data.getNumber()}" th:remove="tag"><li><a th:href="@{/user/listUsers(pageNumber=${pg})}" th:text="${pg+1}"></a></li></span></div></div><!-- 总页数大于5时、中间留五个分页条 --><div th:if="${data.totalPages gt 5}" th:remove="tag"><li th:if="${data.getNumber()-2 ge 0}"><a th:href="@{/user/listUsers(pageNumber=${data.getNumber()}-2)}" th:text="${data.getNumber()-1}"></a></li><li th:if="${data.getNumber()-1 ge 0}"><a th:href="@{/user/listUsers(pageNumber=${data.getNumber()}-1)}" th:text="${data.getNumber()}"></a></li><li><span class="active" th:text="${data.getNumber()+1}"></span></li><li th:if="${data.getNumber()+1 lt data.totalPages}"><a th:href="@{/user/listUsers(pageNumber=${data.getNumber()}+1)}" th:text="${data.getNumber()+2}"></a></li><li th:if="${data.getNumber()+2 lt data.totalPages}"><a th:href="@{/user/listUsers(pageNumber=${data.getNumber()}+2)}" th:text="${data.getNumber()+3}"></a></li></div><li th:if="${data.hasNext()}"><a th:href="@{/user/listUsers(pageNumber=${data.getNumber()}+1)}">下一页</a></li><li><a th:href="@{/user/listUsers(pageNumber=${data.totalPages}-1)}">尾页</a></li><li><span th:utext="'共'+${data.totalPages}+'页 / 总'+${data.totalElements}+'条'"></span></li></ul></div>
</div></body>
</html>
效果:
七、JPA + BootStrap 带条件查询分页
UserController.java
/*** 分页(带条件查询)* @param modelMap* @param pageNumber* @param pageSize* @param userQuery* @return*/
@GetMapping(value = "listUserQuery")
public String listUserQuery(ModelMap modelMap,@RequestParam(value = "pageNumber",defaultValue = "0") Integer pageNumber,@RequestParam(value = "pageSize",defaultValue = "5") Integer pageSize,UserQuery userQuery){//设置分页Pageable pageable = PageRequest.of(pageNumber,pageSize,Sort.Direction.ASC, "id");//进行查询Page<User> userPage = userService.findUserQuery(pageable,userQuery);modelMap.addAttribute("data",userPage);modelMap.addAttribute("name",userQuery.getName());modelMap.addAttribute("sex",userQuery.getSex());modelMap.addAttribute("position",userQuery.getPosition());return "home";
}
UserQuery.java
//数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止使用 Map 类来传输
public class UserQuery {private String name;private Integer sex;private String position;...此处省略get、set
}
UserServiceImpl.java
/*** 分页(带条件查询)* @param pageable* @param userQuery* @return*/
@Override
public Page<User> findUserQuery(Pageable pageable, UserQuery userQuery) {Page<User> userPage = userDao.findAll(new Specification<User>(){@Overridepublic Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {List<Predicate> list = new ArrayList<>();if (StringUtils.isNotBlank(userQuery.getName())){list.add(criteriaBuilder.equal(root.get("name").as(String.class), userQuery.getName()));}if(userQuery.getSex() != null){list.add(criteriaBuilder.equal(root.get("sex").as(Integer.class), userQuery.getSex()));}if (StringUtils.isNotBlank(userQuery.getPosition())){list.add(criteriaBuilder.equal(root.get("position").as(String.class), userQuery.getPosition()));}Predicate[] p = new Predicate[list.size()];return criteriaBuilder.and(list.toArray(p));}},pageable);return userPage;
}
效果1
效果2
八、demo地址、可下载
完整代码已同步至Github,可下载 Github地址 、如果有问题可随时提问,觉得不错,欢迎点赞评论。
最新SpringBoot2.0X整合SpringData JPA实战完整篇相关推荐
- SpringBoot2零基础到项目实战-基础篇
springboot2零基础到项目实战-基础篇 课程内容说明 课程单元 学习目标 基础篇 能够创建SpringBoot工程 基于SpringBoot实现ssm/ssmp整合 应用篇 能够掌握Sprin ...
- 最新C语言/C++语言培训项目实战(完整)
C语言/C++语言培训视频教程 C语言/C++语言培训视频教程 C语言/C++语言培训视频教程 下载地址:百度网盘
- 解决SpringBoot整合SpringData JPA的PagingAndSortingRepository的Sort排序时遇到的错误:has protected access in ‘org.sp
问题: 原因: pringboot2.2.1(含)以上的版本Sort已经不能再实例化了,构造方法已经是私有的了! 解决方法: 我们可以改用Sort.by获得Sort对象
- spring boot 整合多数据源JDBC、多数据源mybatis、多数据源springdata jpa
目录 代码地址:(spring-boot github地址) 1.springboot整合JDBC 2.springboot整合mybatis 3.springboot整合springdata jpa ...
- SpringBoot简介、SpringBoot 入门程序搭建、与JDBC、Druid、Mybatis和SpringData JPA的整合
一.SpringBoot 简介: spring boot并不是一个全新的框架,它不是spring解决方案的一个替代品,而是spring的一个封装.所以,你以前可以用spring做的事情,现在用spri ...
- 黑马 SpringData JPA笔记
课程链接:https://www.bilibili.com/video/BV1Y4411W7Rx?from=search&seid=415951199875837982 第一 orm思想 ...
- SpringBoot2.0整合多数据源拆分
前言 本文环境承接springboot2.0整合使用mybatis(数据访问篇) 一.什么是多数据源 公司分为两个数据库,一个数据库专门存放共同配置文件,一个数据库垂直业务数据库.垂直根据业务划分具体 ...
- SpringBoot2.x整合Redis实战 4节课
1.分布式缓存Redis介绍 简介:讲解为什么要用缓存和介绍什么是Redis,新手练习工具 1.redis官网 https://redis.io/download 2.新 ...
- SpringBoot2.x整合redis实战讲解
SpringBoot2.x整合redis实战讲解 简介:使用springboot-starter整合reids实战 1.官网:https://docs.spring.io/spring-boot/do ...
最新文章
- Java学习笔记13
- leetcode874
- 国内主流.NET CMS系统整理
- Spring boot(3):Spring boot中Redis 的使用
- linux 自动安装 yum,LINUX6安装YUM仓库和实现开机自动挂载
- 【三维深度学习】多视角场景点云重建模型PointMVS
- Round 2—算法的复杂度
- 宝塔面板 服务器状态,宝塔面板中重启腾讯云服务器后无法登录宝塔面板怎么办?...
- linux php muma,php实现Linux服务器木马排查及加固功能
- SurfacePro6解决亮度自动调节问题
- Enriched Feature Guided Refinement Network for Object Detection(面向目标检测的丰富特征引导细化网络)
- window.btoa与window.atob
- 2021江苏省南通市高考成绩查询时间,2021年江苏南通高考时间:6月7日至9日
- Linux下打包命令tar
- 操作系统概念 第六章 同步
- 操作系统可以控制和管理计算机的硬件资源,Windows操作系统是用来控制和管理计算机所有硬件和软件的...
- nth-child选择器
- 中国传统节日网页html,【学习在线】中国传统节日的形成和发展
- 一切还算顺利,远方的你还好吗?
- Matlab exercise04
热门文章
- 信息学奥赛一本通(2052:【例3.2】范围判断)
- 小b删列(51Nod-2523)
- 小b和排序(51Nod-2484)
- 求递推序列的第N项(51Nod-1126)
- 级数求和(洛谷-P1035)
- 10 PP配置-生产主数据-工作中心相关-定义工作中心公式
- re匹配字符串的中间一段_爬虫利器之 re 模块
- cassandra可视化工具_耗时1个月整理!160种Python标准库、第三方库和外部工具都有了...
- 基于android新闻阅读器,Readian News是一款基于Android和网络的新闻阅读器,可让您掌控一切...
- 计算机等级考试机试试题,计算机等级考试二级VFP机试试题18