Spring-Data-JPA初体验(内含demo)

小编 2026-06-18 阅读:890 评论:0
前言 我一直在使用Mybatis作为持久化框架,并且觉得Mybatis十分的不错,足够灵活,虽说需要自己手写sql,但是这也是我觉得的一个优点,直观并且优化方便. 但是我觉得JPA规范也有其优...

前言

我一直在使用Mybatis作为持久化框架,并且觉得Mybatis十分的不错,足够灵活,虽说需要自己手写sql,但是这也是我觉得的一个优点,直观并且优化方便.

但是我觉得JPA规范也有其优点,比如说简单,在一些基本的CRUD操作时,完全无需手写SQL.

因此趁着空闲,对Spring Data JPA做一个了解,并简单的写一个Demo来学习使用.

定义

在本文可能会涉及一下几个概念,这里统一讲一下定义.

JPA

JPA,即Java Persistence API.是Sun公司在Java EE 5规范中提出的Java持久化接口,即一种规范.

ORM

对象关系映射,即Object Relational Mapping,简称ORM.是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.

Hibernate

Hibernate是一种ORM框架,Hibernate在3.2版本开始,已经完全兼容JPA标准.

Mybatis

Mybatis是另外一种ORM框架.使用它构建项目可以看Spring Boot Mybatis Web 开发环境搭建

Spring Data JPA

Spring Data JPA是Spring基于Hibernate开发的一个JPA框架,实现了JPA规范.

Spring Data JPA 实现原理

前文说过,JPA的一个优点就是不用写简单的CRUD的SQL语句,那么怎么做到的呢?

JPA可以通过如下两种方式指定查询语句:

  1. Spring Data JPA 可以访问 JPA 命名查询语句。开发者只需要在定义命名查询语句时,为其指定一个符合给定格式的名字,Spring Data JPA 便会在创建代理对象时,使用该命名查询语句来实现其功能。
  2. 开发者还可以直接在声明的方法上面使用 @Query 注解,并提供一个查询语句作为参数,Spring Data JPA 在创建代理对象时,便以提供的查询语句来实现其功能。

第一种功能基本可以满足日常所需,当需要连表查询或者一些更加复杂的操作室,可以使用@Query注解来使用自己编写的sql进行查询.

方法名和sql的对应关系在文末附录

环境搭建

首先使用Spring Boot 及Maven搭建一个项目,这部分不再赘述,有兴趣可以移步上面的链接.

添加依赖

在pox.xml中添加以下依赖,分别为:

  1. spring-data-jpa
  2. Hibernate-core
  3. Hibernate–annotations
  4. HikariCP

其中第四点为我使用的连接池,Spring Boot官方也比较推荐这个,当然,可以换成C3P0或者其他连接池.

<!-- spring-data-jpa -->
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
</dependency>

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>5.3.7.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-annotations</artifactId>
  <version>3.5.6-Final</version>
</dependency>

<dependency>
  <groupId>com.zaxxer</groupId>
  <artifactId>HikariCP</artifactId>
  <version>3.2.0</version>
</dependency>

配置文件

application.yaml文件中加入以下内容,设置服务启动端口,使用配置为local以及数据源的一些配置,最后是JPA的配置.


server:
  port: 9999

spring:
  profiles:
    active: local
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 0
      initial-size: 5
      maximum-pool-size: 15
      auto-commit: true
      pool-name: NezhaHikariCP
      test-connection-on-checkout: true

  jpa:
    database: MYSQL
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect

同时,新建application-local.yaml中加入以下内容,设置mysql数据源的相关信息.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1/test?characterEncoding=utf8&useSSL=false
    username: root
    password: root
  jpa:
    show-sql: true

环境的搭建就是上面那么简单,第一步添加依赖,第二步添加一些配置就ok.

剩下的就是编写一些业务代码,而各种配置类什么的完全没有!!XML配置也没有!!

Demo创建

创建数据表

首先在数据库中创建表,本文测试表为(在test数据库中):

mysql> desc student;
+------------+-------------+------+-----+---------------------+-----------------------------+
| Field      | Type        | Null | Key | Default             | Extra                       |
+------------+-------------+------+-----+---------------------+-----------------------------+
| id         | int(10)     | NO   |     | NULL                |                             |
| name       | varchar(45) | NO   | PRI | NULL                |                             |
| class_num  | int(12)     | YES  |     | NULL                |                             |
| age        | int(3)      | YES  |     | 18                  |                             |
| created_at | timestamp   | NO   |     | CURRENT_TIMESTAMP   |                             |
| updated_at | timestamp   | NO   |     | 2018-01-01 00:00:00 | on update CURRENT_TIMESTAMP |
+------------+-------------+------+-----+---------------------+-----------------------------+
6 rows in set (0.01 sec)

建表语句为:

CREATE TABLE `student` (
 `id` int(10) NOT NULL AUTO_INCREMENT COMMENT \'id\',
 `name` varchar(45) NOT NULL COMMENT \'姓名\',
 `class_num` int(12) DEFAULT NULL COMMENT \'班级\',
 `age` int(3) DEFAULT \'18\' COMMENT \'年龄\',
 `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT \'创建时间\',
 `updated_at` timestamp NOT NULL DEFAULT \'2018-01-01 00:00:00\' ON UPDATE CURRENT_TIMESTAMP COMMENT \'修改时间\',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

创建实体类

在model包下创建Student实体类:

package com.huyan.demo.model;

import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * created by huyanshi on 2018/12/21
 */
@AllArgsConstructor
@Builder
@Data
@NoArgsConstructor
@Entity
@Table(name = \"student\")
public class Student {

  @Id
  private int id;

  private String name;

  private int classNum;

  private  int age;

  @Temporal(TemporalType.TIMESTAMP)
  private Date createdAt;

  @Temporal(TemporalType.TIMESTAMP)
  private Date updatedAt;
}

其中,@Entity标识此类是一个实体类,@Table指定关联的数据表.

创建dao层接口

package com.huyan.demo.dao;

import com.huyan.demo.model.Student;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * created by huyanshi on 2018/12/21
 */
@Repository
public interface StudentDao extends JpaRepository<Student,String> {

  List<Student> findAll();
}

在接口上打上@Repository注解并实现JpaRepository接口.该接口使用了泛型,需要为其提供两个类型:第一个为该接口处理的域对象类型,第二个为该域对象的主键类型

好,demo到此就结束了,service层和controller随意些,只要调用List<Student> findAll();这个方法,就会查找该表格中的所有数据.

我写了个很简单的接口,直接返回拿到的list,数据结果集为:

\"\"

注意,在这个过程中,我们是没有手写SQL的,如果是在使用mybatis的过程中,我们需要编写select * from student的SQL语句.

更多方法示例

费劲搞了JPA,当然不可写一个方法就完事了.这样在实际应用中没有多少帮助.因此,我将一些常用的方法类型在这里测试一遍使用方法,最后,将其整合输出.

实际测试我才发现,许多的方法在继承的接口中早已定义,比如查询全量,根据主键嗯增删改查,排序,分页等,可谓十分强大,因此简单测试了大于小于及多参数的查询.

以下代码实际运行通过.

@Repository
public interface StudentDao extends JpaRepository<Student, Integer> {

  //查询所有
  List<Student> findAll();
  //查询年龄大于传入值得
  List<Student> findByAgeAfter(int age);
  //查询年龄和班级等于入参的
  List<Student> findByAgeAndClassNum(int age, int classNum);
  //查询年龄为入参的学生,且结果按照创建时间排序
  List<Student> findByAgeOrderByCreatedAt(int age);
  //根据主键更新实体的名字年龄及班级
  @Modifying(clearAutomatically = true)
  @Transactional
  @Query(value = \"UPDATE Student SET name = :name, classNum = :classNum, \"
      + \"age = :age WHERE id = :id \")
  int updateNameAndAgeAndClassNumById(@Param(\"name\") String name, @Param(\"age\") int age,
      @Param(\"classNum\") int classNum, @Param(\"id\") int id);

}

继承哪个接口

在上文中创建dao层接口中,我们要继承Repository接口,但是在Spring Data JPA中,提供了4个接口,到底该继承哪个呢?

  1. Repository接口,没有定义方法.
  2. CrudRepository接口,继承自Repository接口,定义了基本的增删改查.
  3. PagingAndSortingRepository接口,继承自CrudRepository接口,定义了排序及分页方法.
  4. JpaRepository接口,继承自PagingAndSortingRepository接口,提供了 flush(),saveAndFlush(),deleteInBatch() 等方法.

但是要说继承哪个接口呢?这个就见仁见智了,我是在不影响业务(主要是Crudrepository接口会提供删除方法,有时候你并不想提供删除)的情况下,我一般使用JPARepository,毕竟功能比较全嘛.

后话

在今天的学习后,对Jpa也算是有一点了解,在我看来,他和Mysql是两种不同的思路,但是都可以完成同一个任务.

在业务逻辑较为简单的时候,使用JPA可以提高开发效率,因为基本的增删改查你连方法定义都不需要写…然后大部分较简单的查询你都可以通过定义方法名来完成,实在不行还有@Query手写sql兜底.

附录:方法关键字和使用方式及生成的SQL列表

Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age ⇐ ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages)</Age> … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> age)</Age> … where x.age not in ?1
TRUE findByActiveTrue() … where x.active = true
FALSE findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

参考链接

https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/index.html
https://segmentfault.com/a/1190000009866465

完。





ChangeLog

2018-12-22 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com

更多学习笔记见个人博客------>呼延十

版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表