1. 首页
  2. 一起来学springboot2.x

一起来学 SpringBoot 2.x | 第六篇整合SpringDataJpa

作者:唐亚峰 出自: https://blog.battcn.com/


上一篇介绍了 Spring JdbcTemplate的使用,对比原始的 JDBC而言,它更加的简洁。但随着表的增加,重复的CRUD工作让我们苦不堪言,这时候 Spring Data Jpa的作用就体现出来了…..

JPA

JPA是 Java Persistence API的简称,中文名 Java持久层API,是官方(Sun)在JDK5.0后提出的Java持久化规范。其目的是为了简化现有 JAVA EEJAVA SE应用开发工作,以及整合现有的ORM技术实现规范统一

JPA的总体思想和现有 HibernateTopLinkJDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:

  • ORM映射元数据: 支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
  • API: 操作实体对象来执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
  • 查询语言: 通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

JPA只是一种规范,它需要第三方自行实现其功能,在众多框架中 Hibernate是最为强大的一个。从功能上来说,JPA就是Hibernate功能的一个子集。Hibernate 从3.2开始,就开始兼容JPA。同时Hibernate3.2获得了Sun TCK的JPA(Java Persistence API) 兼容认证。

Spring Data JPA

常见的ORM框架中 Hibernate的JPA最为完整,因此 Spring Data JPA 是采用基于JPA规范的 Hibernate框架基础下提供了 Repository层的实现。 Spring Data Repository极大地简化了实现各种持久层的数据库访问而写的样板代码量,同时CrudRepository提供了丰富的CRUD功能去管理实体类。

优点

  • 丰富的API,简单操作无需编写额外的代码
  • 丰富的SQL日志输出

缺点

  • 学习成本较大,需要学习HQL
  • 配置复杂,虽然SpringBoot简化的大量的配置,关系映射多表查询配置依旧不容易
  • 性能较差,对比JdbcTemplateMybatis等ORM框架,它的性能无异于是最差的

导入依赖

pom.xml 中添加 spring-boot-starter-data-jpa 的依赖

  <!-- Spring JDBC 的依赖包,使用 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 将会自动获得HikariCP依赖 -->
    <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>
    <!-- 默认就内嵌了Tomcat 容器,如需要更换容器也极其简单-->
    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 测试包,当我们使用 mvn package 的时候该包并不会被打入,因为它的生命周期只在 test 之内-->
    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-test</artifactId>
     <scope>test</scope>
    </dependency>

连接数据库

application.properties中添加如下配置。值得注意的是,SpringBoot默认会自动配置 DataSource,它将优先采用 HikariCP连接池,如果没有该依赖的情况则选取 tomcat-jdbc,如果前两者都不可用最后选取 Commons DBCP2通过spring.datasource.type属性可以指定其它种类的连接池 ``` spring.datasource.url=jdbc:mysql://localhost:3306/chapter5?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false spring.datasource.password=root spring.datasource.username=root #spring.datasource.type

JPA配置

spring.jpa.hibernate.ddl-auto=update

输出日志

spring.jpa.show-sql=true

数据库类型

spring.jpa.database=mysql


> ddl-auto 几种属性 * **create:** 每次运行程序时,都会重新创建表,故而数据会丢失 * **create-drop:** 每次运行程序时会先创建表结构,然后待程序结束时清空表 * **upadte:** 每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用) * **validate:** 运行程序会校验数据与数据库的字段类型是否相同,**字段不同会报错** ## 具体编码 由于上面我们采用的是`spring.jpa.hibernate.ddl-auto=update`方式,因此这里可以跳过手动建表的操作 ### 实体类 JPA规范注解坐落在`javax.persistence`包下,**`@Id`注解一定不要引用错了,否则会报错**。**`@GeneratedValue(strategy = GenerationType.IDENTITY)`自增策略,不需要映射的字段可以通过`@Transient`注解排除掉** > 常见的几种自增策略 * **TABLE:** 使用一个特定的数据库表格来保存主键 * **SEQUENCE:** 根据底层数据库的序列来生成主键,条件是数据库支持序列。这个值要与generator一起使用,generator 指定生成主键使用的生成器(可能是orcale中自己编写的序列)。 * **IDENTITY:** 主键由数据库自动生成(主要是支持自动增长的数据库,如mysql) * **AUTO:** 主键由程序控制,也是GenerationType的默认值。 ```java package com.battcn.entity; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import java.io.Serializable; /** * @author Levin * @since 2018/5/7 0007 */ @Entity(name = "t_user") public class User implements Serializable { private static final long serialVersionUID = 8655851615465363473L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; /** * TODO 忽略该字段的映射 */ @Transient private String email; // TODO 省略get set } ```java # Repository ### 创建 `UserRepository`数据访问层接口,需要继承 `JpaRepository<T,K>`, **第一个泛型参数是实体对象的名称,第二个是主键类型**。只需要这样简单的配置,该 `UserRepository`就拥常用的 `CRUD`功能, `JpaRepository`本身就包含了常用功能,剩下的查询我们按照规范写接口即可, **`JPA支持@Query`注解写HQL,也支持`findAllByUsername`这种根据字段名命名的方式(强烈推荐`IntelliJ IDEA`对JPA支持非常NICE)**
package com.battcn.repository;

import com.battcn.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * t_user 操作
 *
 * @author Levin
 * @since 2018/5/7 0007
 */
@Repository
public interface UserRepository extends JpaRepository&lt;User, Long> {

 /**
 * 根据用户名查询用户信息
 *
 * @param username 用户名
 * @return 查询结果
 */
 List&lt;User> findAllByUsername(String username);
}
# 测试 ###

完成数据访问层接口后,最后编写一个 `junit`测试类来检验代码的正确性。 下面的几个操作中,只有 `findAllByUsername`是我们自己编写的代码,其它的都是继承自 `JpaRepository`接口中的方法,更关键的是分页及排序是如此的简单实例化一个 `Pageable`即可…

package com.battcn;

import com.battcn.entity.User;
import com.battcn.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

/**
 * @author Levin
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter5ApplicationTests {

 private static final Logger log = LoggerFactory.getLogger(Chapter5ApplicationTests.class);

 @Autowired
 private UserRepository userRepository;

 @Test
 public void test1() throws Exception {
 final User user = userRepository.save(new User(&quot;u1&quot;, &quot;p1&quot;));
 log.info(&quot;[添加成功] - [{}]&quot;, user);
 final List&lt;User> u1 = userRepository.findAllByUsername(&quot;u1&quot;);
 log.info(&quot;[条件查询] - [{}]&quot;, u1);
 Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Order.desc(&quot;username&quot;)));
 final Page&lt;User> users = userRepository.findAll(pageable);
 log.info(&quot;[分页+排序+查询所有] - [{}]&quot;, users.getContent());
 userRepository.findById(users.getContent().get(0).getId()).ifPresent(user1 -> log.info(&quot;[主键查询] - [{}]&quot;, user1));
 final User edit = userRepository.save(new User(user.getId(), &quot;修改后的ui&quot;, &quot;修改后的p1&quot;));
 log.info(&quot;[修改成功] - [{}]&quot;, edit);
 userRepository.deleteById(user.getId());
 log.info(&quot;[删除主键为 {} 成功] - [{}]&quot;, user.getId());
 }
}

“`java
总结 ##

更多内容请参考 官方文档 目前很多大佬都写过关于 SpringBoot 的教程了,如有雷同,请多多包涵,本教程基于最新的 spring-boot-starter-parent:2.0.1.RELEASE编写,包括新版本的特性都会一起介绍…

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
  4. JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

    本文著作权归作者所有,如若转载,请注明出处

    转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

    标题:一起来学 SpringBoot 2.x | 第六篇整合SpringDataJpa

    链接:https://www.javajike.com/article/3364.html

« 一起来学 SpringBoot 2.x | 第七篇整合Mybatis
一起来学 SpringBoot 2.x | 第五篇使用JdbcTemplate访问数据库»

相关推荐

QR code