vlambda博客
学习文章列表

微服务框架【第4期】--SpringBoot整合SpringDataJpa基础

微服务框架【第4期】--SpringBoot整合SpringDataJpa基础

导读:

    大家好,我是老田。今天我们看下SpringBoo整合SpringDataJpa。SpringDataJpa是SpringData家族的一部分,提供了一套基于JPA 标准操作数据库的简化方案。底层默认的是依赖 HibernateJPA 来实现的。今天我们先梳理SpringDataJpa的基础语法。

1.JPA简介

JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。值得注意的是,JPA 是在充分吸收了现有 Hibernate,TopLink,JDO 等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。总的来说,JPA包括以下3方面的技术:

  • ORM映射元数据:支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系

  • API:操作实体对象来执行CRUD操作

  • 查询语言:通过面向对象而非面向数据库的查询语言(JPQL)查询数据,避免程序的SQL语句紧密耦合

2.JPA 的优势

标准化:JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问 API,这保证了基于 JPA 开发的企业应用能够经过少量的修改就能够在不同的 JPA 框架下运行。

容器级特性的支持:JPA 框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

简单方便:JPA 的主要目标之一就是提供更加简单的编程模型:在 JPA 框架下创建实体和创建 Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity 进行注释,JPA 的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA 基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成

查询能力:JPA 的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是 Hibernate HQL 的等价物。JPA 定义了独特的 JPQL(Java Persistence Query Language),JPQL 是 EJB QL 的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

高级特性:JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

3.JPA 与 hibernate 的关系

JPA 规范本质上就是一种 ORM 规范,注意不是 ORM 框架。因为 JPA 并未提供 ORM 实现,它只是制订了一些规范,提供了一些编程的 API 接口,但具体实现则由服务厂商来提供实现。JPA 和 Hibernate 的关系就像 JDBC 和 JDBC 驱动的关系,JPA 是规范,Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现。

4.Spring Data Jpa

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 JPA 技术实现,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!

spring data jpa 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现

5.引入SpringDataJpa

maven

 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
 </dependency>
 
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-jpa</artifactId>
 </dependency>

application.properties

 spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
 spring.datasource.username=root
 spring.datasource.password=root
 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 spring.jpa.properties.hibernate.hbm2ddl.auto=update
 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
 spring.jpa.show-sql=true

配置就这么简单,下面简单介绍下spring.jpa.properties.hibernate.hbm2ddl.auto有几种配置:

  • create:每次加载Hibernate时都会删除上一次生成的表(包括数据),然后重新生成新表。

  • create-drop:每次加载Hibernate时都会生成表,但当SessionFactory关闭时,所生成的表将自动删除。

  • update:最常用的属性值,第一次加载Hibernate时创建数据表(前提是需要先有数据库),以后加载Hibernate时不会删除上一次生成的表,会根据实体更新,只新增字段,不会删除字段(即使实体中已经删除)。

  • validate:每次加载Hibernate时都会验证数据表结构,只会和已经存在的数据表进行比较,根据model修改表结构,但不会创建新表。

6.Repository

Repository 接口是 SpringDataJPA 的核心接口,它不提供任何方法,开发者需要在自己定义的接口中声明需要的方法。

基础的 Repository 提供了最基本的数据访问功能,其几个子接口则扩展了一些功能,它的几个常用的实现类如下:

  • CrudRepository:继承 Repository,实现了一组 CRUD 相关的方法

  • PagingAndSortingRepository:继承 CrudRepository,实现了一组分页排序相关的方法

  • JpaRepository:继承 PagingAndSortingRepository,实现一组 JPA 规范相关的方法

  • 自定义的 XxxxRepository 需要继承 JpaRepository,这样的 XxxxRepository 接口就具备了通用的数据访问控制层的能力。

  • JpaSpecificationExecutor:不属于Repository体系,实现一组 JPA Criteria 查询相关的方法

Repository 提供了两种查询方式的支持

  1. 基于方法名称命名规则查询

  2. 基于@Query 注解查询

7.方法定义规范

简单条件查询

  • 按照 Spring Data 的规范,查询方法以 find | read | get 开头

  • 涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性以首字母大写

  • 使用And条件连接时,条件的属性名称与个数要与参数的位置与个数一一对应

  • 支持属性的级联查询. 若当前类有符合条件的属性, 则优先使用, 而不使用级联属性. 若需要使用级联属性, 则属性之间使用 _ 进行连接.

查询举例:

  1. 按照id查询

    User getUserById(Long id);

    User getById(Long id);

  2. 查询所有年龄小于90岁的人

    List<User> findByAgeLessThan(Long age);

  3. 查询所有姓赵的人

    List<User> findByUsernameStartingWith(String u);

  4. 查询所有姓赵的、并且id大于50的人

    List<User> findByUsernameStartingWithAndIdGreaterThan(String name, Long id);

  5. 查询所有姓名中包含”上”字的人

    List<User> findByUsernameContaining(String name);

  6. 查询所有姓赵的或者年龄大于90岁的

    List<User> findByUsernameStartingWithOrAgeGreaterThan(String name, Long age);

  7. 查询所有角色为1的用户

    List<User> findByRole_Id(Long id);

8.方法定义规范支持的关键字

支持的查询关键字如下图:

微服务框架【第4期】--SpringBoot整合SpringDataJpa基础

9.@Query注解

有的时候,这里提供的查询关键字并不能满足我们的查询需求,这个时候就可以使用 @Query 关键字,来自定义查询 SQL,例如查询Id最大的User:

 @Query("select u from 实体类名 u where 属性=(select max(id) from 实体类名)")
 User getMaxIdUser();

如果查询有参数的话,参数有两种不同的传递方式:

1.利用下标索引传参,索引参数如下所示,索引值从1开始,查询中 ”?X” 个数需要与方法定义的参数个数相一致,并且顺序也要一致:

 @Query("select u from 实体类名 u where 属性>?1 and 属性 like ?2")
 List<User> selectUserByParam(Long id, String name);

2.命名参数(推荐):这种方式可以定义好参数名,赋值时采用@Param(“参数名”),而不用管顺序:

 @Query("select u from 实体类名 u where 属性>:id and 属性 like :name")
 List<User> selectUserByParam2(@Param("name") String name, @Param("id") Long id);
 

查询时候,也可以是使用原生的SQL查询,如下:

 @Query(value = "select * from t_user",nativeQuery = true)
 List<User> selectAll();

10.@Modifying注解

涉及到数据修改操作,可以使用 @Modifying 注解,@Query 与 @Modifying 这两个 annotation一起声明,可定义个性化更新操作,例如涉及某些字段更新时最为常用,示例如下:

 @Modifying
 @Query("update t_user set age=:age where id>:id")
 int updateUserById(@Param("age") Long age, @Param("id") Long id);

注意:

  1. 可以通过自定义的 JPQL 完成 UPDATE 和 DELETE 操作. 注意: JPQL 不支持使用 INSERT

  2. 方法的返回值应该是 int,表示更新语句所影响的行数

  3. 在调用的地方必须加事务,没有事务不能正常执行

  4. 默认情况下, Spring Data 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作


博观而约取,厚积而薄发!


--END--