来说说JPA、Hibernate、Spring Data JPA之间的什么关系?
来说说JPA、Hibernate、Spring Data JPA之间的什么关系
Java 持久层框架访问数据库的方式大致分为两种:一种以 SQL 核心,封装一定程度的 JDBC 操作,比如: MyBatis。另一种是以 Java 实体类为核心,将实体类的和数据库表之间建立映射关系,也就是我们说的ORM框架,如:Hibernate、Spring Data JPA。
JPA
Spring Data JPA是建立的JPA的基础之上, 那到底什么是JPA呢?
我们都知道不同的数据库厂商都有自己的实现类,后来统一规范也就有了数据库驱动,Java在操作数据库的时候,底层使用的其实是JDBC,而JDBC是一组操作不同数据库的规范。我们的Java应用程序,只需要调用JDBC提供的API就可以访问数据库了,而JPA也是类似的道理。
JPA全称为Java Persistence API(Java持久层API),它是Sun公司在JavaEE 5中提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具,来管理Java应用中的关系数据,JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。很多ORM框架都是实现了JPA的规范,如:Hibernate、EclipseLink。
需要注意的是JPA统一了Java应用程序访问ORM框架的规范。
JPA为我们提供了以下规范:
ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。
JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发人员不用再写SQL了。
JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
Hibernate
Hibernate是Java中的对象关系映射解决方案。对象关系映射或ORM框架是将应用程序数据模型对象映射到关系数据库表的技术。Hibernate 不仅关注于从 Java 类到数据库表的映射,也有 Java 数据类型到 SQL 数据类型的映射。
Hibernate 和 JPA是什么关系呢
上面我们介绍到JPA是Java EE 5规范中提出的Java持久化接口,而Hibernate是一个ORM框架
JPA和Hibernate的关系:
• JPA是一个规范,而不是框架
• Hibernate是JPA的一种实现,是一个框架
Spring Data是啥
Spring Data是Spring 社区的一个子项目,主要用于简化数据(关系型&非关系型)访问,其主要目标是使得数据库的访问变得方便快捷。
• 它提供很多模板操作
– Spring Data Elasticsearch
– Spring Data MongoDB
– Spring Data Redis
– Spring Data Solr
• 强大的 Repository 和定制的数据储存对象的抽象映射
• 对数据访问对象的支持
Spring Data JPA
Spring Data JPA是在实现了JPA规范的基础上封装的一套 JPA 应用框架,虽然ORM框架都实现了JPA规范,但是在不同的ORM框架之间切换仍然需要编写不同的代码,而使用Spring Data JPA能够方便大家在不同的ORM框架之间进行切换而不需要更改代码。Spring Data JPA旨在通过将统一ORM框架的访问持久层的操作,来提高开发人的效率。
Spring Data JPA和Hibernate的关系
Hibernate其实是JPA的一种实现,而Spring Data JPA是一个JPA数据访问抽象。也就是说Spring Data JPA不是一个实现或JPA提供的程序,它只是一个抽象层,主要用于减少为各种持久层存储实现数据访问层所需的样板代码量。但是它还是需要JPA提供实现程序,其实Spring Data JPA底层就是使用的 Hibernate实现。
总结就是:
• Hibernate是JPA的一种实现,是一个框架
• Spring Data JPA是一种JPA的抽象层,底层依赖Hibernate
实践
理论一定要与实践相结合
1、首先,我们需要配置pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2、然后是application.properties
的配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/数据库名字?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create
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
修改表结构,但不会创建新表。不配置此项,表示禁用自动建表功能
spring.jpa.show-sql=true
该配置当在执行数据库操作的时候会在控制台打印 sql
语句,方便我们检查排错等。
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
这是数据库的方言配置。
3、接下来我们建立用户实体类
@Entity
public class User {
@Id
@GeneratedValue
private long id;
@Column(nullable = false, unique = true)
private String userName;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private int age;
}
这里的一些注解解释如下:
@Entity 是一个类注解,用来注解该类是一个实体类用来进行和数据库中的表建立关联关系,首次启动项目的时候,默认会在数据中生成一个同实体类相同名字的表(table),也可以通过注解中的
name
属性来修改表(table)名称, 如@Entity(name=“user”) , 这样数据库中表的名称则是user
。该注解十分重要,如果没有该注解首次启动项目的时候你会发现数据库没有生成对应的表。@Table 注解也是一个类注解,该注解可以用来修改表的名字,该注解完全可以忽略掉不用,@Entity 注解已具备该注解的功能。
@Id 类的属性注解,该注解表明该属性字段是一个主键,该属性必须具备,不可缺少。
@GeneratedValue 该注解通常和 @Id 主键注解一起使用,用来定义主键的呈现形式,该注解通常有多种使用策略,先总结如下:
@GeneratedValue(strategy= GenerationType.IDENTITY) 该注解由数据库自动生成,主键自增型,在 mysql 数据库中使用最频繁,oracle 不支持。
@GeneratedValue(strategy= GenerationType.AUTO) 主键由程序控制,默认的主键生成策略,
oracle
默认是序列化的方式,mysql
默认是主键自增的方式。@GeneratedValue(strategy= GenerationType.SEQUENCE) 根据底层数据库的序列来生成主键,条件是数据库支持序列,
Oracle
支持,Mysql
不支持。@GeneratedValue(strategy= GenerationType.TABLE) 使用一个特定的数据库表格来保存主键,较少使用。
@Column 是一个类的属性注解,该注解可以定义一个字段映射到数据库属性的具体特征,比如字段长度,映射到数据库时属性的具体名字等。
@Transient 是一个属性注解,该注解标注的字段不会被映射到数据库当中。
4、声明 UserRepository
接口,继承JpaRepository
,如下所示
public interface UserRepository extends JpaRepository<User, Long> {
}
这里的 JpaRepository
继承了接口PagingAndSortingRepository
和QueryByExampleExecutor
。而PagingAndSortingRepository
又继承CrudRepository
。
因此,JpaRepository
接口同时拥有了基本CRUD
功能以及分页功能。因此,这里我们可以继承JpaRepository
,从而获得Spring
为我们预先定义的多种基本数据操作方法。
5、然后我们定义一个测试类, 这里我们演示下添加操作, @Transactional 表示开启事务防止出现脏数据。
……
@Autowired
private UserRepository userRepository;
@Test
@Transactional
public void userAddTest() {
User user = new User();
user.setUserName("李嘉图");
user.setAge(30);
user.setPassword("123456");
userRepository.save(user);
User item = userRepository.findByUserName("ljt");
log.info(JsonUtils.toJson(item));
}
6、接下来我们说下查询,查询可以分为基本查询和自定义查询,一种是 spring data
默认已经实现,只需要要继承JpaRepository
,一种是根据查询的方法来自动解析成 SQL
。
@Test
public void testQuery() throws Exception {
User user=new User();
userRepository.findAll();
userRepository.findOne(1l);
userRepository.save(user);
userRepository.delete(user);
userRepository.count();
userRepository.exists(1l);
……
}
7、自定义的简单查询就是根据方法名来自动生成SQL
,主要的语法是findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy
后面跟属性名称,举几个例子:
User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);
Long deleteById(Long id);
Long countByUserName(String userName);
List<User> findByEmailLike(String email);
User findByUserNameIgnoreCase(String userName);
List<User> findByUserNameOrderByEmailDesc(String email);
8、接下来,我们说下复杂的查询,在实际的开发中我们需要用到分页、删选、连表等查询的时候就需要特殊的方法或者自定义 SQL
。
以分页查询为例,分页查询在实际使用中非常普遍了,spring data jpa
已经帮我们实现了分页的功能,在查询的方法中,需要传入参数Pageable
,当查询中有多个参数的时候Pageabl
e建议做为最后一个参数传入。Pageable
是 spring
封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。
Page<User> findALL(Pageable pageable);
Page<User> findByUserName(String userName,Pageable pageable);
9、我们看下下面的测试用例
@Test
public void testPageQuery() throws Exception {
int page=1,size=5;
Sort sort = new Sort(Direction.DESC, "id");
Pageable pageable = new PageRequest(page, size, sort);
userRepository.findALL(pageable);
userRepository.findByUserName("testName", pageable);
}
Spring data大部分的SQL都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的 SQL来查询,spring data
也是完美支持的,如下所示:
@Modifying
@Query("update User u set u.userName = ?1 where c.id = ?2")
int modifyByIdAndUserId(String userName, Long id);
@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteByUserId(Long id);
@Transactional(timeout = 10)
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
来说说JPA、Hibernate、Spring Data JPA之间的什么关系?的更多相关文章
- jdbc、jpa、spring data jpa、hibernate、mybatis之间的关系及区别
基础概念 jdbc(Java DataBase Connectivity)是java连接数据库操作的原生接口.JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型.作为A ...
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的理由!
序言 Spring Data JPA作为Spring Data中对于关系型数据库支持的一种框架技术,属于ORM的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度. 本文档隶属于< ...
- 63.JPA/Hibernate/Spring Data概念【从零开始学Spring Boot】
[从零开始学习Spirng Boot-常见异常汇总] 事情的起源,无意当中在一个群里看到这么一句描述:"有人么?默默的问一句,现在开发用mybatis还是hibernate还是jpa&quo ...
- Spring boot之JPA/Hibernate/Spring Data
1.什么是JPA? JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA(Java Per ...
- 简述 JPA 与 Spring Data JPA 与 Hibernate
1.JPA是什么?以及相关概述 JPA的是 Java Persistence API 的简写,是Sun官方提出的一种ORM规范! Sun提出此规范有2个原因: 1.简化现有Java EE和Java S ...
- Spring Data JPA简介 Spring Data JPA特点
Spring Data JPA 是Spring基于ORM框架.JPA规范的基础上封装的一套JPA 应用框架,底层使用了Hibernate 的JPA技术实现,可使开发者用极简的代码即可实现对数据的访问和 ...
- 【jpa】spring data jpa 配置使用
1.spring data jpa 简单介绍 jpa是用于对象持久化的API,jpa是一种规范,而其他的ORM框架(hibernate,topLink等)是其实现,所以jpa可以使用不同的实现方式,修 ...
- <Spring Data JPA>二 Spring Data Jpa
1.pom依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- [Spring Boot] Adding JPA and Spring Data JPA
JPA is just like a helper class for providing data for Controller, has method like 'findOne', 'findA ...
- 【hibernate spring data jpa】执行了save()方法 sql语句也执行了,但是数据并未插入数据库中
执行了save()方法 sql语句也执行了,但是数据并未插入数据库中 解决方法: 是因为执行了save()方法,也执行了sql语句,但是因为使用的是 @Transactional 注解,不是手动去提 ...
随机推荐
- Linux系统的内核编译
<1>给虚拟机分配2048M内存 <2>配置高可用yum源 <3>下载软件 <1>安装内核源码包 根据依赖性提示,安装对应的包 下载并安装软件包(3个) ...
- Java基础(二)——内部类
一.内部类 内部类(Inner Class)就是定义在一个类里面的类.与之对应,包含内部类的类被称为外部类.内部类可以用private修饰. 1.为什么要定义内部类?或者内部类的作用是什么? 内部类提 ...
- Python - repr()、str() 的区别
总的来说 str():将传入的值转换为适合人阅读的字符串形式 repr():将传入的值转换为 Python 解释器可读取的字符串形式 传入整型 # number resp = str(1) print ...
- www迁移
www迁移主要就是2部分: 1)官网页面架构,即 ./drupal/index.php 2)官网图片,即 ./drupal/assets/ 目录下的文件 1. 在ubuntu上搭建基础v1.0环境 2 ...
- C# Dapper基本三层架构使用 (二、Model)
我们将数据存放在数据库中,数据表的结构,我们通常会用一个类来抽象,表的属性就是类的属性,我们通常将表的一行存储在一个类中. 在Java中,通常将其称为实体类Entity,在C#中,通常将其称为Mode ...
- js 点击复制文字
复制input里面的文字 html: <input id="content" class="form-control" type="text&q ...
- RMI源码调试
看RMI漏洞时候,对其漏洞原理并不是很理解,所以简单调试了下源码加强下漏洞理解 由于要调试到RegistryImpl_Stub这种动态类,刚开始用的源码版本是JDK8u141,后来发现源码有些地方进行 ...
- 利用协程爬网页,自动切换io 精典案例:
首先Python提供的协程库gevent好像并不能知道那些程序使用了io 所以要加一个补丁,mondey,以下同步和异步各爬一次的案例 : , from urllib import requesti ...
- docker学习笔记(一)--ubunru18.04下面安装docker18.03
我是在本地安装的虚拟机,再搭建的环境,虚拟机的安装可以参考下面的博客: https://blog.csdn.net/u013142781/article/details/50529030 安装好了之后 ...
- 【Python机器学习实战】决策树与集成学习(七)——集成学习(5)XGBoost实例及调参
上一节对XGBoost算法的原理和过程进行了描述,XGBoost在算法优化方面主要在原损失函数中加入了正则项,同时将损失函数的二阶泰勒展开近似展开代替残差(事实上在GBDT中叶子结点的最优值求解也是使 ...