专栏首页JavaEEspringData Jpa 快速入门前言:一、简介:二、JPA核心概念:三、springboot集成jpa案例:总结:

springData Jpa 快速入门前言:一、简介:二、JPA核心概念:三、springboot集成jpa案例:总结:

前言:

数据持久化的操作,一般都要由我们自己一步步的去编程实现,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一样。

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

6、controller层: UserController.java:

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserDao userDao;

    /**
     * 查询所有用户
     * 
     * @param model
     * @return
     */
    @GetMapping
    public ModelAndView list(Model model) {
        model.addAttribute("userList", userDao.findAll());
        model.addAttribute("title", "用户管理");
        return new ModelAndView("user/list", "userModel", model);
    }

    /**
     * 根据id查询用户
     * 
     * @param id
     * @param model
     * @return
     */
    @GetMapping("{id}")
    public ModelAndView view(@PathVariable("id") Long id, Model model) {
        User user = userDao.findOne(id);
        model.addAttribute("user", user);
        model.addAttribute("title", "查看用户");
        return new ModelAndView("user/view", "userModel", model);
    }

    /**
     * 获取创建表单页面
     * 
     * @param model
     * @return
     */
    @GetMapping("/form")
    public ModelAndView createForm(Model model) {
        model.addAttribute("user", new User());
        model.addAttribute("title", "创建用户");
        return new ModelAndView("user/form", "userModel", model);
    }

    /**
     * 保存或更新用户
     * 
     * @param user
     * @return
     */
    @PostMapping
    public ModelAndView saveOrUpdateUser(User user) {
        user = userDao.save(user);
        return new ModelAndView("redirect:/users");
    }

    /**
     * 删除用户
     * 
     * @param id
     * @return
     */
    @GetMapping("/delete/{id}")
    public ModelAndView delete(@PathVariable("id") Long id) {
        userDao.delete(id);
        return new ModelAndView("redirect:/users");// 重定向到list页面
    }

    /**
     * 获取修改用户的界面
     * 
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/modify/{id}")
    public ModelAndView modify(@PathVariable("id") Long id, Model model) {
        User user = userDao.findOne(id);
        model.addAttribute("user", user);
        model.addAttribute("title", "修改用户");
        return new ModelAndView("user/form", "userModel", 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的也是一样的开发方法,只是添加依赖的方式不同而已。

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Thymeleaf的使用前言:一、thymeleaf简介:二、thymeleaf标准方言:三、thymeleaf与springboot集成案例:总结:

    最近听说thymeleaf好像也挺流行的,还说是spring官方推荐使用,那thymeleaf究竟是什么呢?spring为什么推荐用它呢?怎么用呢?本文将为你揭...

    贪挽懒月
  • mybatis笔记整理mybatis的基本用法及配置:

    贪挽懒月
  • 探讨Java参数传递问题

    可能很多人都知道参数有形参和实参之分,却不知道区别到底是什么;知道Java中内存分为栈、堆、方法区等5片内存,不知道每片内存中保存的都是什么;关于参数的传递到底...

    贪挽懒月
  • Thymeleaf的使用前言:一、thymeleaf简介:二、thymeleaf标准方言:三、thymeleaf与springboot集成案例:总结:

    最近听说thymeleaf好像也挺流行的,还说是spring官方推荐使用,那thymeleaf究竟是什么呢?spring为什么推荐用它呢?怎么用呢?本文将为你揭...

    贪挽懒月
  • JS-时间处理函数封装汇总 (更新中...)

    最近听说thymeleaf好像也挺流行的,还说是spring官方推荐使用,那thymeleaf究竟是什么呢?spring为什么推荐用它呢?怎么用呢?本文将为你揭...

    xing.org1^
  • 一次线上Mysql死锁分析

    这个表用来保存用户的收货地址,下单时需要选择相应的收货地址;通过查看日志平台日志,出问题的主要发生在添加地址的场景。

    心平气和
  • 带你认识 flask 粉丝

    每个用户维护一个“粉丝”用户列表和“关注”用户列表。不幸的是,关系型数据库没有列表类型的字段来保存它们,那么只能通过表的现有字段和他们之间的关系来实现。

    公众号---志学Python
  • 学校比赛网站设计

    @坤的
  • sql 删除重复的数据,保留一条,并且保留update_time最大的那条

    近期面试的时候,考官出了一道题,当时没有做出来。第二天灵光乍现吧,写出来了,特此记录一下。

    Theone67
  • 逆向华为路由器第三部分

    引文 在前面两个部分(1,2)已经介绍了UART,BusyBox等部分的逆向调试,而这篇将会开始在流量分析方面下手,来逆向出更多的信息。 正文 请看下图,数据存...

    FB客服

扫码关注云+社区

领取腾讯云代金券