Springboot - 集成 JPA
1.什么是 JPA?
JPA就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
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 才能够提供的高级查询特性,甚至还能够支持子查询。
- 5高级特性 JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。
3.JPA的核心概念
3.1 实体
- 实体表示关系数据库中的表
- 每个实体对应该表的行
- 使用 javax.persistence.Entity 注解
- 必须有 public 或 protected 的无参构造函数
- 当实体以分离对象方式传递,必须实现 Serializable 接口
- 必须有唯一的对象标识符,即简单主键 或 复合主键
3.2 关系
- 一对一 @OneToOne
- 一对多 @OneToMany
- 多对一 @ManyToOne
- 多对多 @ManyToMany
3.3 EntityManager
- 定义用于持久性上下文交互的方法
4.Spring Data JPA
41. 什么是 Spring Data JPA
- 是Spring Data 的一个子项目,它通过提供基于JPA的 Repository 极大了减少了操作 JPA 的代码。
- 对于 JPA 数据访问层的封装与增强。
Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。
Spring Data 包含多个子项目:
- Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化
- Hadoop - 基于 Spring 的 Hadoop 作业配置和一个 POJO 编程模型的 MapReduce 作业
- Key-Value - 集成了 Redis 和 Riak ,提供多个常用场景下的简单封装
- Document - 集成文档数据库:CouchDB 和 MongoDB 并提供基本的配置映射和资料库支持
- Graph - 集成 Neo4j 提供强大的基于 POJO 的编程模型
- Graph Roo AddOn - Roo support for Neo4j
- JDBC Extensions - 支持 Oracle RAD、高级队列和高级数据类型
- JPA - 简化创建 JPA 数据访问层和跨存储的持久层功能
- Mapping - 基于 Grails 的提供对象映射框架,支持不同的数据库
- Examples - 示例程序、文档和图数据库
- Guidance - 高级文档
4.2 Spring Data JPA 常用接口
5.基于注解的使用
5.1 JPA拥有哪些注解
注解 | 解释 |
---|---|
@Entity | 声明类为实体或表。 |
@Table | 声明表名。 |
@Basic | 指定非约束明确的各个字段。 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性。 |
@Id | 指定的类的属性,用于识别(一个表中的主键)。 |
@GeneratedValue | 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。 |
@Transient | 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。 |
@Column | 指定持久属性栏属性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。 |
@AccessType | 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束。 |
@ColumnResult | 参考使用select子句的SQL查询中的列名。 |
@ManyToMany | 定义了连接表之间的多对多一对多的关系。 |
@ManyToOne | 定义了连接表之间的多对一的关系。 |
@OneToMany | 定义了连接表之间存在一个一对多的关系。 |
@OneToOne | 定义了连接表之间有一个一对一的关系。 |
@NamedQueries | 指定命名查询的列表。 |
@NamedQuery | 指定使用静态名称的查询。 |
6.实例
6.1maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
6.2 数据源和JPA配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mytest
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver //驱动
jpa:
hibernate:
ddl-auto: update //自动更新
show-sql: true //日志中显示sql语句 jpa.hibernate.ddl-auto是hibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下: ·
create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。 ·
create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,
即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
6.3创建实体以及数据访问接口
// Person.java @Entity
public class Person { @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; @Column(name = "name", nullable = true, length = 20)
private String name; @Column(name = "agee", nullable = true, length = 4)
private int age; get ... set...
}
接着是 Dao 接口,改接口只需要继承JpaRepository接口即可。
public interface PersonRepository extends JpaRepository<Person, Long> {
}
或者注解的方式
@RepositoryDefinition(domainClass = Person.class, idClass = Integer.class)
public interface PersonRepository { }
写一个rest接口以供测试使用
@RestControllerpublic class PerconController { @Autowired
private PersonRepository personRepository; @PostMapping(path = "addPerson")
public void addPerson(Person person) {
personRepository.save(person);
} @DeleteMapping(path = "deletePerson")
public void deletePerson(Long id) {
personRepository.delete(id);
}
}
6.4编写自己的方法
6.4.1 在repository接口中添加如下查询方法
Person findByName(String name);
6.4.2 rest接口调用
public Object getPerson(@QueryParam("name") String name) {
return personRepository.findByName(name);
}
6.4.3 那么JPA是通过什么规则来根据方法名生成sql语句查询的呢
其实JPA在这里遵循Convention over configuration(约定大约配置)的原则,遵循spring 以及JPQL定义的方法命名。Spring提供了一套可以通过命名规则进行查询构建的机制。这套机制会把方法名首先过滤一些关键字,比如 find…By, read…By, query…By, count…By 和 get…By 。系统会根据关键字将命名解析成2个子语句,第一个 By 是区分这两个子语句的关键词。这个 By 之前的子语句是查询子语句(指明返回要查询的对象),后面的部分是条件子语句。如果直接就是 findBy… 返回的就是定义Respository时指定的领域对象集合,同时JPQL中也定义了丰富的关键字:and、or、Between等等,下面我们来看一下JPQL中有哪些关键字:
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and |
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 ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection 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) |
6.5 自己编写查询语句。
如果是一些很复杂的查询,那么方法名就会变得很长很长,读起来很辛苦。可以通过注解的方式,将自己写的SQL语句传进去。
@RepositoryDefinition(domainClass = Student.class, idClass = Integer.class)
public interface StudentRepository {
//注意,这里from后的不是数据表名,而是对于的实体类名
@Query("select o from Student o where id=(select max(id) from Student t1)")
public Student getStudentByMaxId();
//这里的?是占位符,在执行是会替换成对应位置的参数,比如这里?1会被替换成name的值
@Query("select o from Student o where o.name=?1 and o.age=?2")
public List<Student> queryParams1(String name, Integer age);
//这里的:+参数名则是绑定参数,在参数列中使用@Param注解绑定参数,则可在SQL语句中使用:+参数名得到相应参数的值
@Query("select o from Student o where o.name=:name and o.age=:age")
public List<Student> queryParams2(@Param("name")String name, @Param("age")Integer age);
}
使用@Quer注解传入SQL语句,我们就可以实现一些比较复杂的查询。除了查询,我们平时还会有更新、插入、删除的操作。
要实现插入、更新、删除操作,我们只需要再多加一个注解@Modifying,告诉框架,它是一个DML操作即可。
@RepositoryDefinition(domainClass = Student.class, idClass = Integer.class)
public interface StudentRepository {
@Modifying
@Query("update Student o set o.age = :age where o.id = :id")
public void update(@Param("id")Integer id, @Param("age")Integer age);
}
又或许你必须要使用原生的SQL语句怎么办?只需要在@Query注解中设置nativeQuery即可
@RepositoryDefinition(domainClass = Student.class, idClass = Integer.class)
public interface StudentRepository {
//注意,这里使用原生的SQL语句,from后的表名应该是数据库表名
@Query(nativeQuery = true, value = "select count(1) from student")
public long getCount();
}
7.声明式事务
SpringBoot默认已经帮我们自动配置好了JPATransaction,我们直接使用即可。
直接在Service层测试@Transactional,当然正常的事务隔离级别还有事务传递方式还是和以前Spring一样配置。注意这个@Transactional是Spring提供的,不要错误的使用JPA的@Transactional
以上就是jpa的简单实用和介绍。
Springboot - 集成 JPA的更多相关文章
- Spring Data JPA系列2:SpringBoot集成JPA详细教程,快速在项目中熟练使用JPA
大家好,又见面了. 这是Spring Data JPA系列的第2篇,在上一篇<Spring Data JPA系列1:JDBC.ORM.JPA.Spring Data JPA,傻傻分不清楚?给你个 ...
- springboot 集成 jpa/hibernate
pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- springboot支付项目之springboot集成jpa
springboot集成spring-jpa 本文主要内容: 1:spring boot怎么集成spring-jpa以及第一个jpa查询示例 如jpa几个常用注解.lombok注解使用 2:怎么设置i ...
- springboot集成jpa
spring data jpa简介 spring data jpa是spring基于hibernate及jpa规范封装出来的一套持久层框架.该框架极大的降低了开发者工作量,提升开发效率.提供的关键字可 ...
- SpringBoot系列:四、SpringBoot集成JPA
首先要明白的是JPA不是产品,它是一个规范. Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范.它为 Java 开发人员提供了一种对象/关联映射工具来 ...
- springboot集成jpa操作mybatis数据库
数据库如下 CREATE TABLE `jpa`.`Untitled` ( `cust_id` bigint() NOT NULL AUTO_INCREMENT, `cust_address` var ...
- 12 — springboot集成JPA — 更新完毕
1.什么是jpa? 一堆不想整在这博客里面的理论知识.这些理论玩意儿就应该自行领悟到自己脑海里 1).JPA & Spring Data JPA 1.1).JPA JPA是Java Persi ...
- springboot集成jpa,在postgresql数据库中创建主键自增表
依赖文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:/ ...
- SpringBoot集成JPA根据实体类自动生成表
数据库是mysql,在application.properties中的写法如下: 原来配置这样的时候确实可以生产表的 #spring.jpa.hibernate.ddl-auto=update 多方查 ...
随机推荐
- c#帮助类:发送邮件
private static string IsOpenSendMail = ConfigurationManager.AppSettings["IsOpenSendMail"]; ...
- VS Code 运行html文件
用VS Code编写html文件,想在VS Code中直接打开运行,配置如下: 配置tasks.json 打开VS Code,点击"终端",选择"配置任务". ...
- cinder create volume的流程-scheduler调度
创建 Volume 时,cinder-scheduler 会基于容量.Volume Type 等条件选择出最合适的存储节点,然后让其创建 Volume. 1.cinder-scheduler配置相关项 ...
- 关于nmake cl.exe error 0xc0000135
[问题] F:\STLport-5.1.4\build\lib>nmake /f msvc.mak cl /nologo /W4 /Wp64 /GR /EHsc /Zm800 /GL /MD / ...
- php中的静态方法实例理解
<?php header("content-type:text/html;charset=utf-8"); class Human{ static public $name ...
- HTML5 indexedDb 数据库
indexedDb 数据库 上一节中,我们知道了,HMTL5中内置了两种本地数据库,一种是通过SQL语言来访问的文件型SQL数据库被称为“SQLLite,另一种是是被称为indexedDB 的数据 ...
- pytest的一些你爱不释手的插件
1. pytest-html 安装: pip install pytest-html # 通过pip安装pytest-html 运行测试文件的时候,命令行加上对应参数即可 比如:pytest test ...
- Qt 学习之路 2(46):视图和委托
Home / Qt 学习之路 2 / Qt 学习之路 2(46):视图和委托 Qt 学习之路 2(46):视图和委托 豆子 2013年3月11日 Qt 学习之路 2 63条评论 前面我们介绍了 ...
- Android 日历视图(Calendarview)
1.介绍 2.常用属性 3.xml文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayou ...
- nginx 之 proxy_pass
nginx中有两个模块都有proxy_pass指令 ngx_http_proxy_module的proxy_pass 语法: proxy_pass URL; 场景: location, if in l ...