打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
初识SpringData JPA
关于数据持久化

数据持久化的操作,一般都要由我们自己一步步的去编程实现。mybatis通过我们编写xml实现,hibernate也要配置对应的xml然后通过创建session执行crud操作。那么有没有这样一种技术,就是把底层的这些crud操作都封装好了,我们直接调用方法就行了,答案是有的,通过springData Jpa 就可以实现。

01

SpringData 

JPA
简介

springData,显然也是spring家族的,data,顾名思义,它就是操作数据的一个框架。jpa,全称为Java persistence api,是用来管理java ee 或Java se环境中的持久化、以及对象关系映射的api,hibernate就是它的一个实现。当jpa遇上springData,就是见证奇迹的时候!它们俩在一起,dao层我们基本上无需再写代码,只需定义接口就可以了,一般的实现都不用我们写了,我们只需调用即可。

02

JPA

核心概念

1、实体:实体表示关系数据库中的表,每个实体实例对应该表中的一条记录,实体类应该有标识其为实体的注解,还应该有唯一的对象标识符,简单主键或复合主键。

2、关系:关系无外乎一下几种:

一对一: @OneToOne

一对多: @OneToMany

多对一: @ManyToOne

多对多: @ManyToMany

3、EntityManager:

这个就相当于hibernate的session、mybatis的sqlsessionFactory,定义用于与持久性上下文进行交互的方法。








03

springboot

集成jpa

案例

1、添加依赖:build.gradle:

  1. buildscript {

  2.    ext {

  3.        springBootVersion = '1.5.2.RELEASE'

  4.    }

  5.    //自定义版本

  6.    ext['thymeleaf.version'] = '3.0.3.RELEASE'

  7.    ext['thymeleaf-layout-dialect.version'] = '2.2.0'

  8.    ext['hibernate.version'] = '5.2.8.Final'

  9.    repositories {

  10.        mavenCentral()

  11.    }

  12.    dependencies {

  13.        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")

  14.    }

  15. }

  16. apply plugin: 'java'

  17. apply plugin: 'eclipse'

  18. apply plugin: 'org.springframework.boot'

  19. apply plugin: 'io.spring.dependency-management'

  20. group = 'com.zhu'

  21. version = '0.0.1-SNAPSHOT'

  22. sourceCompatibility = 1.8

  23. repositories {

  24.    mavenCentral()

  25. }

  26. dependencies {

  27.    //jpa依赖

  28.    compile('org.springframework.boot:spring-boot-starter-data-jpa')

  29.    compile('org.springframework.boot:spring-boot-starter-web')

  30.    //thymeleaf依赖

  31.    compile('org.springframework.boot:spring-boot-starter-thymeleaf')

  32.    //mysql驱动

  33.    compile('mysql:mysql-connector-java:6.0.5')

  34.    //H2数据库

  35.    runtime('com.h2database:h2:1.4.193')

  36.    testCompile('org.springframework.boot:spring-boot-starter-test')

  37. }

2、配置thymeleaf、H2和jpa:

application.properties:

  1. #thymeleaf相关配置

  2. spring.thymeleaf.encoding=UTF-8

  3. spring.thymeleaf.cache=false

  4. spring.thymeleaf.mode=HTML5

  5. #启用h2控制台

  6. spring.h2.console.enabled=true

  7. #jpa相关配置

  8. spring.jpa.show-sql=true

  9. spring.jpa.hibernate.ddl-auto=update

注意:这里没有配置mysql,先演示H2数据库的用法;

  1. spring.jpa.hibernate.ddl-auto

的值有以下几个: create ---- 每次运行该程序,没有表格会新建表格,表内有数据会清空;

create-drop ---- 每次程序结束的时候会清空表;

update ---- 每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新;

validate ---- 运行程序会校验数据与数据库的字段类型是否相同,不同会报错。 所以一般情况下用 update就行了。

3、实体层:

User.java:

  1. import javax.persistence.Entity;

  2. import javax.persistence.GeneratedValue;

  3. import javax.persistence.GenerationType;

  4. import javax.persistence.Id;

  5. @Entity // 标识这个类是实体

  6. public class User {

  7.    @Id // 标识主键

  8.    @GeneratedValue(strategy=GenerationType.IDENTITY) //自增策略

  9.    private Long id;

  10.    private String name;

  11.    private String email;

  12. }

注意:这里省略了set、get方法以及构造方法; 这样自动建表时表中字段与属性名一致,比如name属性对应数据库表中字段也是name,如果要自定义,可以用在属性上用 @Column()注解; 表名默认与实体类名一致,可以在类上加 @Table()注解来自定义。

4、dao层:

UserDao.java:

  1. public interface UserDao extends CrudRepository<User, Long> {

  2. }

注意:第一:这个就是简单的实现crud操作,所以继承 CrudRepository即可,其它接口如下:

(1)、 Repository:标记型接口,表示任何继承它的类都是仓库接口类。

(2)、 CrudRepository:包含了10种crud方法。

(3)  PagingAndSortingRepository:除了10中crud方法外,多了分页和排序。

(4)、 JpaRepository:比(3)又多了一些其他的常用方法。 所以在项目开发中继承 JpaRepository就行了。

第二:springData Jpa 还可以自定义方法,只要符合命名规范,就不用我们自己实现。比如要根据用户名和密码查询用户,就可以定义一个 findByNameAndPwd()方法,直接调用就行,不需要自己实现。命名规范如下图:

第三:其实这里取名 UserDao不太好, daoDataAccessObjects的缩写,意思为数据访问对象,这里使用Jpa,根据命名规范应该叫做 UserRepository,就像mybatis中应该叫做 UserMapper一样。

第四:jpa没有直接提供分页方法,若是要分页,请看下面的例子:接口中的方法:

  1. Page<User> findByAge(int age, Pageable pageable);

调用时:

  1. Pageable pageable = PageRequest.of(page,size);

  2. Page<User> result = UserRepository.findByAge(20,pageable);

上述代码表示分页查询age为20的的User。先要构建一个Pageable对象,传入分页信息,再把pageable对象传入查询方法中。

5、service层:因为本案例service层并无其他逻辑,所以直接省略。

6、controller层:

UserController.java:

  1. @RestController

  2. @RequestMapping("/users")

  3. public class UserController {

  4.    @Autowired

  5.    private UserDao userDao;

  6.    /**

  7.     * 查询所有用户

  8.     *

  9.     * @param model

  10.     * @return

  11.     */

  12.    @GetMapping

  13.    public ModelAndView list(Model model) {

  14.        model.addAttribute("userList", userDao.findAll());

  15.        model.addAttribute("title", "用户管理");

  16.        return new ModelAndView("user/list", "userModel", model);

  17.    }

  18.    /**

  19.     * 根据id查询用户

  20.     *

  21.     * @param id

  22.     * @param model

  23.     * @return

  24.     */

  25.    @GetMapping("{id}")

  26.    public ModelAndView view(@PathVariable("id") Long id, Model model) {

  27.        User user = userDao.findOne(id);

  28.        model.addAttribute("user", user);

  29.        model.addAttribute("title", "查看用户");

  30.        return new ModelAndView("user/view", "userModel", model);

  31.    }

  32.    /**

  33.     * 获取创建表单页面

  34.     *

  35.     * @param model

  36.     * @return

  37.     */

  38.    @GetMapping("/form")

  39.    public ModelAndView createForm(Model model) {

  40.        model.addAttribute("user", new User());

  41.        model.addAttribute("title", "创建用户");

  42.        return new ModelAndView("user/form", "userModel", model);

  43.    }

  44.    /**

  45.     * 保存或更新用户

  46.     *

  47.     * @param user

  48.     * @return

  49.     */

  50.    @PostMapping

  51.    public ModelAndView saveOrUpdateUser(User user) {

  52.        user = userDao.save(user);

  53.        return new ModelAndView("redirect:/users");

  54.    }

  55.    /**

  56.     * 删除用户

  57.     *

  58.     * @param id

  59.     * @return

  60.     */

  61.    @GetMapping("/delete/{id}")

  62.    public ModelAndView delete(@PathVariable("id") Long id) {

  63.        userDao.delete(id);

  64.        return new ModelAndView("redirect:/users");// 重定向到list页面

  65.    }

  66.    /**

  67.     * 获取修改用户的界面

  68.     *

  69.     * @param id

  70.     * @param model

  71.     * @return

  72.     */

  73.    @GetMapping("/modify/{id}")

  74.    public ModelAndView modify(@PathVariable("id") Long id, Model model) {

  75.        User user = userDao.findOne(id);

  76.        model.addAttribute("user", user);

  77.        model.addAttribute("title", "修改用户");

  78.        return new ModelAndView("user/form", "userModel", model);

  79.    }

  80. }

从上面的代码可以看到,虽然dao层只是简单的继承了CrudRepository,没有做任何实现,但是我们在controller层调用时却可以使用 findOnefindAlldeletesave方法,底层已经帮我们实现这些方法了,我们只需调用就行了。

7、前端:

页头:header.html

  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org"

  3.      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

  4. <head>

  5. <meta charset="UTF-8">

  6. <title>thymeleaf in action</title>

  7. </head>

  8. <body>

  9. <div th:fragment="header">

  10.   <h1>Thymeleaf in action</h1>

  11.   <a href="/users" >首页</a>

  12. </div>

  13. </body>

  14. </html>

页脚:footer.html

  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org"

  3.      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

  4. <head>

  5. <meta charset="UTF-8">

  6. <title>thymeleaf in action</title>

  7. </head>

  8. <body>

  9. <div th:fragment="footer">

  10.   <a href="#" >邮箱</a>

  11. </div>

  12. </body>

  13. </html>

form.html:

  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org"

  3.      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

  4. <head>

  5. <meta charset="UTF-8">

  6. <title>thymeleaf in action</title>

  7. </head>

  8. <body>

  9. <div th:replace="~{fragments/header :: header}"></div>

  10. <h3 th:text="${userModel.title}">test</h3>

  11. <form action="/users" th:action="@{/users}" method="POST" th:object="${userModel.user}">

  12.   <input type="hidden" name="id" th:value="*{id}">

  13.   名称:<br>

  14.   <input type="text" name="name" th:value="*{name}"><br>

  15.   邮箱:<br>

  16.   <input type="text" name="email"th:value="*{email}">

  17.   <input type="submit" value="提交">

  18. </form>

  19. <div th:replace="~{fragments/footer :: footer}"></div>

  20. </body>

  21. </html>

list.html:

  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org"

  3.      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

  4. <head>

  5. <meta charset="UTF-8">

  6. <title>thymeleaf in action</title>

  7. </head>

  8. <body>

  9. <!-- 引用头部信息 -->

  10. <!-- 在fragments下的header文件下有名为header的片段 -->

  11. <div th:replace="~{fragments/header :: header}"></div>

  12. <h3 th:text="${userModel.title}"></h3>

  13. <div>

  14.   <a href="/users/form.html" th:href="@{/users/form}">创建用户</a>

  15. </div>

  16. <table border="1">

  17.   <thead>

  18.      <tr>

  19.         <td>ID</td>

  20.         <td>Email</td>

  21.         <td>Name</td>

  22.      </tr>

  23.   </thead>

  24.   <tbody>

  25.     <tr th:if="${userModel.userList.size()} eq 0">

  26.         <td colspan="3">没有用户信息</td>

  27.     </tr>

  28.     <tr th:each="user : ${userModel.userList}">

  29.         <td th:text="${user.id}"></td>

  30.         <td th:text="${user.email}"></td>

  31.         <td ><a th:href="@{'/users/'+${user.id}}" th:text="${user.name}"></a></td>

  32.     </tr>

  33.   </tbody>

  34. </table>

  35. <div th:replace="~{fragments/footer :: footer}"></div>

  36. </body>

  37. </html>

view.html:

  1. <!DOCTYPE html>

  2. <html xmlns:th="http://www.thymeleaf.org"

  3.      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

  4. <head>

  5. <meta charset="UTF-8">

  6. <title>thymeleaf in action</title>

  7. </head>

  8. <body>

  9. <div th:replace="~{fragments/header :: header}"></div>

  10. <h3 th:text="${userModel.title}">test</h3>

  11. <div>

  12.   <p><strong>ID:</strong><span th:text="${userModel.user.id}"></span></p>

  13.   <p><strong>Name:</strong><span th:text="${userModel.user.name}"></span></p>

  14.   <p><strong>Email:</strong><span th:text="${userModel.user.email}"></span></p>

  15. </div>

  16. <div>

  17.   <a th:href="@{'/users/delete/'+${userModel.user.id}}">删除</a>

  18.   <a th:href="@{'/users/modify/'+${userModel.user.id}}">修改</a>

  19. </div>

  20. <div th:replace="~{fragments/footer :: footer}"></div>

  21. </body>

  22. </html>

8、测试:创建用户:

用户列表:

点击用户名字还可以进行删除和修改操作,这里不再截图。接下来说说H2数据库。

9、H2数据库:

H2数据库是一个内存数据库,数据保存在内存中,项目一重启数据就没了。且其无需安装任何服务或者客户端,要在项目中使用也不用怎么配置,直接添加其依赖即可。那么如何查看数据是否保存到了H2数据库中呢?它提供了一个网页版控制台,网址为 http://localhost:8080/h2-console,这个控制台默认是不启用的,所以刚才在application.properties中加上了 spring.h2.console.enabled=true配置。开启后,访问该网址就会出现如下界面:

点击connect就可以查看到数据:
注意,如果你首次登录 http://localhost:8080/h2-console,JDBC URL显示的不是 jdbc:h2:mem:testdb,就要改成这个,否则进去看不到数据。

如果使用了H2数据库后还想使用MySQL,只需要在appication.properties中加上其配置即可,如下:

  1. #配置MySQL数据源

  2. spring.datasource.url=jdbc:mysql:///blog?useSSL=false&serverTimezone=GMT

  3. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

  4. spring.datasource.username=#

  5. spring.datasource.password=#

H2数据库会自动检测你有没有配置其他数据库,如果配置了,H2就会退出江湖,如果把mysql的配置注释掉了,H2就会重出江湖。

值得注意的是:如果你的MySQL驱动用的是6.0以上的版本,要像上面一样在jdbc的url中添加 serverTimezone=GMT,否则会报错。

04

总结

springData Jpa十分强大,有了它,dao层几乎不需要自己写了。上面的案例只是演示了简单的crud,其他方法以及自定义方法老铁们也可以试一试。还有这个项目是基于gradle的,基于maven的也是一样的开发方法,只是添加依赖的方式不同而已。

END


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Spring Boot :模版引擎 Thymeleaf 渲染 Web 页面
spring
java版b2b2c社交电商spring cloud分布式微服务(十三)使用Spring Security安全控制
SpringMVC框架介绍
spring boot:thymeleaf给fragment传递参数的方法
springboot模板
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服