前言:

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

一、简介:

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

二、JPA核心概念:

1、实体:

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

2、关系:

关系无外乎一下几种:

一对一: @OneToOne

一对多: @OneToMany

多对一: @ManyToOne

多对多: @ManyToMany

3、EntityManager:

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

三、springboot集成jpa案例:

本案例使用gradle构建,前端使用thymeleaf,数据库用到了H2和mysql,使用jpa完成crud操作。

1、添加依赖:

build.gradle:

buildscript {
ext {
springBootVersion = '1.5.2.RELEASE'
}
//自定义版本
ext['thymeleaf.version'] = '3.0.3.RELEASE'
ext['thymeleaf-layout-dialect.version'] = '2.2.0'
ext['hibernate.version'] = '5.2.8.Final'
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
} apply plugin: 'java'

apply plugin: 'eclipse'

apply plugin: 'org.springframework.boot'

apply plugin: 'io.spring.dependency-management' group = 'com.zhu'

version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8 repositories {

mavenCentral()

} dependencies {

//jpa依赖

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

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

//thymeleaf依赖

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

//mysql驱动

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

//H2数据库

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

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

}

2、配置thymeleaf、H2和jpa:

application.properties:

#thymeleaf相关配置
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML5
#启用h2控制台
spring.h2.console.enabled=true
#jpa相关配置
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update

注意:

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

spring.jpa.hibernate.ddl-auto的值有以下几个:

create ---- 每次运行该程序,没有表格会新建表格,表内有数据会清空;

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

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

validate ---- 运行程序会校验数据与数据库的字段类型是否相同,不同会报错。

所以一般情况下用update就行了。

3、实体层:

User.java:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id; @Entity // 标识这个类是实体

public class User {

@Id // 标识主键

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

private Long id;

private String name;

private String email;

}

注意:

这里省略了set、get方法以及构造方法;

这样自动建表时表中字段与属性名一致,比如name属性对应数据库表中字段也是name,如果要自定义,可以用在属性上用@Column()注解;

表名默认与实体类名一致,可以在类上加@Table()注解来自定义。

4、dao层:

UserDao.java:

public interface UserDao extends CrudRepository<User, Long> {
}

注意:

第一:

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

(1)、Repository:

标记型接口,表示任何继承它的类都是仓库接口类。

(2)、CrudRepository:

包含了10种crud方法。

(3)、PagingAndSortingRepository:

除了10中crud方法外,多了分页和排序。

(4)、JpaRepository:

比(3)又多了一些其他的常用方法。

所以在项目开发中继承JpaRepository就行了。

第二:

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

image.png
image.png

第三:

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

第四:

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

接口中的方法:

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

调用时:

 Pageable pageable = PageRequest.of(page,size);
Page<User> result = UserRepository.findByAge(20,pageable);

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

5、service层:

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

6、controller层:

UserController.java:

@RestController
@RequestMapping("/users")
public class UserController {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserDao userDao; <span class="hljs-comment">/**
* 查询所有用户
*
* <span class="hljs-doctag">@param</span> model
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-meta">@GetMapping</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">list</span><span class="hljs-params">(Model model)</span> </span>{
model.addAttribute(<span class="hljs-string">"userList"</span>, userDao.findAll());
model.addAttribute(<span class="hljs-string">"title"</span>, <span class="hljs-string">"用户管理"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ModelAndView(<span class="hljs-string">"user/list"</span>, <span class="hljs-string">"userModel"</span>, model);
} <span class="hljs-comment">/**
* 根据id查询用户
*
* <span class="hljs-doctag">@param</span> id
* <span class="hljs-doctag">@param</span> model
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"{id}"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">view</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"id"</span>)</span> Long id, Model model) </span>{
User user = userDao.findOne(id);
model.addAttribute(<span class="hljs-string">"user"</span>, user);
model.addAttribute(<span class="hljs-string">"title"</span>, <span class="hljs-string">"查看用户"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ModelAndView(<span class="hljs-string">"user/view"</span>, <span class="hljs-string">"userModel"</span>, model);
} <span class="hljs-comment">/**
* 获取创建表单页面
*
* <span class="hljs-doctag">@param</span> model
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/form"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">createForm</span><span class="hljs-params">(Model model)</span> </span>{
model.addAttribute(<span class="hljs-string">"user"</span>, <span class="hljs-keyword">new</span> User());
model.addAttribute(<span class="hljs-string">"title"</span>, <span class="hljs-string">"创建用户"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ModelAndView(<span class="hljs-string">"user/form"</span>, <span class="hljs-string">"userModel"</span>, model);
} <span class="hljs-comment">/**
* 保存或更新用户
*
* <span class="hljs-doctag">@param</span> user
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-meta">@PostMapping</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">saveOrUpdateUser</span><span class="hljs-params">(User user)</span> </span>{
user = userDao.save(user);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ModelAndView(<span class="hljs-string">"redirect:/users"</span>);
} <span class="hljs-comment">/**
* 删除用户
*
* <span class="hljs-doctag">@param</span> id
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/delete/{id}"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">delete</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"id"</span>)</span> Long id) </span>{
userDao.delete(id);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ModelAndView(<span class="hljs-string">"redirect:/users"</span>);<span class="hljs-comment">// 重定向到list页面</span>
} <span class="hljs-comment">/**
* 获取修改用户的界面
*
* <span class="hljs-doctag">@param</span> id
* <span class="hljs-doctag">@param</span> model
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/modify/{id}"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">modify</span><span class="hljs-params">(@PathVariable(<span class="hljs-string">"id"</span>)</span> Long id, Model model) </span>{
User user = userDao.findOne(id);
model.addAttribute(<span class="hljs-string">"user"</span>, user);
model.addAttribute(<span class="hljs-string">"title"</span>, <span class="hljs-string">"修改用户"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ModelAndView(<span class="hljs-string">"user/form"</span>, <span class="hljs-string">"userModel"</span>, model);
}

}

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

7、前端:

页头:header.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:fragment="header">
<h1>Thymeleaf in action</h1>
<a href="/users" >首页</a>
</div>
</body>
</html>

页脚:footer.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:fragment="footer">
<a href="#" >邮箱</a>
</div>
</body>
</html>

form.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}">test</h3>
<form action="/users" th:action="@{/users}" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
名称:<br>
<input type="text" name="name" th:value="*{name}"><br>
邮箱:<br>
<input type="text" name="email"th:value="*{email}">
<input type="submit" value="提交">
</form>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>

list.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<!-- 引用头部信息 -->
<!-- 在fragments下的header文件下有名为header的片段 -->
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}"></h3>
<div>
<a href="/users/form.html" th:href="@{/users/form}">创建用户</a>
</div> <table border="1">

<thead>

<tr>

<td>ID</td>

<td>Email</td>

<td>Name</td>

</tr>

</thead>

<tbody>

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

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

</tr>

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

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

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

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

</tr> </tbody>

</table>

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

</body>

</html>

view.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}">test</h3>
<div>
<p><strong>ID:</strong><span th:text="${userModel.user.id}"></span></p>
<p><strong>Name:</strong><span th:text="${userModel.user.name}"></span></p>
<p><strong>Email:</strong><span th:text="${userModel.user.email}"></span></p>
</div>
<div>
<a th:href="@{'/users/delete/'+${userModel.user.id}}">删除</a>
<a th:href="@{'/users/modify/'+${userModel.user.id}}">修改</a>
</div>
<div th:replace="~{fragments/footer :: footer}"></div> </body>

</html>

8、测试:

创建用户:

image.png

用户列表:

image.png

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

9、H2数据库:

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

image.png

点击connect就可以查看到数据:

image.png

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

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

#配置MySQL数据源
spring.datasource.url=jdbc:mysql:///blog?useSSL=false&serverTimezone=GMT
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=#
spring.datasource.password=#

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

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

总结:

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

以上内容属于个人笔记整理,如有错误,欢迎批评指正!

      </div>

原文地址:

springData Jpa 快速入门的更多相关文章

  1. SpringData JPA快速入门和基本的CRUD操作以及Specifications条件查询

    SpringData JPA概述: SpringData JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作 ...

  2. Spring Data JPA —— 快速入门

    一.概述 JPA : Java Persistence API, Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. Spring D ...

  3. JPA快速入门(自用)

    该案例为JPA的实体映射案例,将该项目解压导入到myeclipse中即可使用,然后直接使用hibernate即可! 文件地址:files.cnblogs.com/mrwangblog/JPA-Hibe ...

  4. Spring data JPA 快速入门

    1需求 ​ 向客户中插入一条数据 ​ 如果使用Jpa框架可以不用先建表 可以使用框架生成表 ​ 2 实现步骤 ​ a 创建工程 使用maven管理工程 <properties>       ...

  5. 【原创】SpringBoot & SpringCloud 快速入门学习笔记(完整示例)

    [原创]SpringBoot & SpringCloud 快速入门学习笔记(完整示例) 1月前在系统的学习SpringBoot和SpringCloud,同时整理了快速入门示例,方便能针对每个知 ...

  6. SpringData 基于SpringBoot快速入门

    SpringData 基于SpringBoot快速入门 本章通过学习SpringData 和SpringBoot 相关知识将面向服务架构(SOA)的单点登录系统(SSO)需要的代码实现.这样可以从实战 ...

  7. springdata jpa使用Example快速实现动态查询

    Example官方介绍 Query by Example (QBE) is a user-friendly querying technique with a simple interface. It ...

  8. SpringBoot整合SpringData JPA入门到入坟

    首先创建一个SpringBoot项目,目录结构如下: 在pom.xml中添加jpa依赖,其它所需依赖自行添加 <dependency> <groupId>org.springf ...

  9. Mybatis3 快速入门

    Mybatis3 快速入门 目前常见的持久层java框架有Hibernate,Mybatis,SpringData.笔者比较喜欢用SpringData.Hibernate 和 Mybatis 也经常用 ...

随机推荐

  1. Codeforces Round #235 (Div. 2) D (dp)

    以为是组合,后来看着像数位dp,又不知道怎么让它不重复用..然后就没思路 了. 其实状压就可以了 状压是可以确定一个数的使用顺序的 利用01也可以确定所有的数的使用以及不重复 dp[i+1<&l ...

  2. AJPFX简述可变参数概述和使用

    A:可变参数概述 定义方法的时候不知道该定义多少个参数 B:格式 修饰符 返回值类型 方法名(数据类型… 变量名){} C:注意事项: 这里的变量其实是一个数组 如果一个方法有可变参数,并且有多个参数 ...

  3. 深入学习数据结构之bitmap(四)

    Bitmap,今天我们来分析一下bitmap的实现原理以及它的使用场景. 一.使用场景: 1.对于大量数据(几千个数据的就不要在废话了),且无重复或者可以忽略重复的数字.为啥这里要强调无重复,因为在b ...

  4. 学习笔记 第九章 使用CSS美化表格

    第9章  使用CSS美化表格 学习重点 正确使用表格标签: 设置表格和单元格属性: 设计表格的CSS样式. 9.1 表格的基本结构 表格由行.列.单元格3部分组成,单元格时行与列交叉的部分. 在HTM ...

  5. 微信小程序组件解读和分析:十一、label标签

    label标签组件说明: label标签,与html的label标签基本一样.label 元素不会向用户呈现任何特殊效果.不过,它为鼠标用户改进了可用性.如果您在 label 元素内点击文本,就会触发 ...

  6. 安卓(Android )软键盘的控制(显示和隐藏)

    Activity 启动时软键盘默认状态 在清单文件(manifest .xml)中可以通过在 Activity 标签中增加属性控制软键盘的默认状态: android:windowSoftInputMo ...

  7. iOS programming UITabBarController

    iOS programming UITabBarController 1.1 View controllers become more interesting when the user's acti ...

  8. RGB、YUV和YCbCr介绍【转】

    RGB: 就是常说的红(Red).绿(Green)和蓝(Blue),每个图像的像素点由RGB三个通道的值组成. YUV和YCbCr: YUV与RGB的转换: Y'= 0.299*R' + 0.587* ...

  9. Farseer.net轻量级ORM开源框架 V1.x 入门篇:视图的数据操作

    导航 目   录:Farseer.net轻量级ORM开源框架 目录 上一篇:Farseer.net轻量级ORM开源框架 V1.x 入门篇:视图实体类映射 下一篇:Farseer.net轻量级ORM开源 ...

  10. Java处理ZIP文件的解决方案——Zip4J(不解压直接通过InputStream形式读取其中的文件,解决中文乱码)

    一.JDK内置操作Zip文件其实,在JDK中已经存在操作ZIP的工具类:ZipInputStream. 基本使用: public static Map<String, String> re ...