jpa介紹以及在spring boot中使用詳解
1.什么是jpa呢?
JPA顧名思義就是Java Persistence API的意思,是JDK 5.0注解或XML描述對(duì)象-關(guān)系表的映射關(guān)系,并將運(yùn)行期的實(shí)體對(duì)象持久化到數(shù)據(jù)庫中。
2.jpa具有什么優(yōu)勢(shì)?
2.1標(biāo)準(zhǔn)化
JPA 是 JCP 組織發(fā)布的 Java EE 標(biāo)準(zhǔn)之一,因此任何聲稱符合 JPA 標(biāo)準(zhǔn)的框架都遵循同樣的架構(gòu),提供相同的訪問API,這保證了基于JPA開發(fā)的企業(yè)應(yīng)用能夠經(jīng)過少量的修改就能夠在不同的JPA框架下運(yùn)行。
2.2容器級(jí)特性的支持
JPA框架中支持大數(shù)據(jù)集、事務(wù)、并發(fā)等容器級(jí)事務(wù),這使得 JPA 超越了簡單持久化框架的局限,在企業(yè)應(yīng)用發(fā)揮更大的作用。
2.3簡單方便
JPA的主要目標(biāo)之一就是提供更加簡單的編程模型:在JPA框架下創(chuàng)建實(shí)體和創(chuàng)建Java 類一樣簡單,沒有任何的約束和限制,只需要使用 javax.persistence.Entity進(jìn)行注釋,JPA的框架和接口也都非常簡單,沒有太多特別的規(guī)則和設(shè)計(jì)模式的要求,開發(fā)者可以很容易的掌握。JPA基于非侵入式原則設(shè)計(jì),因此可以很容易的和其它框架或者容器集成。
2.4查詢能力
JPA的查詢語言是面向?qū)ο蠖敲嫦驍?shù)據(jù)庫的,它以面向?qū)ο蟮淖匀徽Z法構(gòu)造查詢語句,可以看成是Hibernate HQL的等價(jià)物。JPA定義了獨(dú)特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一種擴(kuò)展,它是針對(duì)實(shí)體的一種查詢語言,操作對(duì)象是實(shí)體,而不是關(guān)系數(shù)據(jù)庫的表,而且能夠支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能夠提供的高級(jí)查詢特性,甚至還能夠支持子查詢。
2.5高級(jí)特性
JPA 中能夠支持面向?qū)ο蟮母呒?jí)特性,如類之間的繼承、多態(tài)和類之間的復(fù)雜關(guān)系,這樣的支持能夠讓開發(fā)者最大限度的使用面向?qū)ο蟮哪P驮O(shè)計(jì)企業(yè)應(yīng)用,而不需要自行處理這些特性在關(guān)系數(shù)據(jù)庫的持久化。
3.基于注解的使用
本篇只介紹注解的使用,另一種基于xml方式的使用大家有興趣可以自行了解一下。
3.1 JPA擁有哪些注解呢?
注解 | 解釋 |
---|---|
@Entity | 聲明類為實(shí)體或表。 |
@Table | 聲明表名。 |
@Basic | 指定非約束明確的各個(gè)字段。 |
@Embedded | 指定類或它的值是一個(gè)可嵌入的類的實(shí)例的實(shí)體的屬性。 |
@Id | 指定的類的屬性,用于識(shí)別(一個(gè)表中的主鍵)。 |
@GeneratedValue | 指定如何標(biāo)識(shí)屬性可以被初始化,例如自動(dòng)、手動(dòng)、或從序列表中獲得的值。 |
@Transient | 指定的屬性,它是不持久的,即:該值永遠(yuǎn)不會(huì)存儲(chǔ)在數(shù)據(jù)庫中。 |
@Column | 指定持久屬性欄屬性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的屬性的值。它創(chuàng)建了一個(gè)序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定屬性的值發(fā)生器。它創(chuàng)造了的值生成的表。 |
@AccessType | 這種類型的注釋用于設(shè)置訪問類型。如果設(shè)置@AccessType(FIELD),則可以直接訪問變量并且不需要getter和setter,但必須為public。如果設(shè)置@AccessType(PROPERTY),通過getter和setter方法訪問Entity的變量。 |
@JoinColumn | 指定一個(gè)實(shí)體組織或?qū)嶓w的集合。這是用在多對(duì)一和一對(duì)多關(guān)聯(lián)。 |
@UniqueConstraint | 指定的字段和用于主要或輔助表的唯一約束。 |
@ColumnResult | 參考使用select子句的SQL查詢中的列名。 |
@ManyToMany | 定義了連接表之間的多對(duì)多一對(duì)多的關(guān)系。 |
@ManyToOne | 定義了連接表之間的多對(duì)一的關(guān)系。 |
@OneToMany | 定義了連接表之間存在一個(gè)一對(duì)多的關(guān)系。 |
@OneToOne | 定義了連接表之間有一個(gè)一對(duì)一的關(guān)系。 |
@NamedQueries | 指定命名查詢的列表。 |
@NamedQuery | 指定使用靜態(tài)名稱的查詢。 |
了解了注解之后我們來看看如何使用吧
4.代碼實(shí)戰(zhàn)
4.1maven依賴
添加jpa起步依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
4.2配置文件
在application.yml文件中添加如下配置
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 //驅(qū)動(dòng) jpa: hibernate: ddl-auto: update //自動(dòng)更新 show-sql: true //日志中顯示sql語句
jpa.hibernate.ddl-auto是hibernate的配置屬性,其主要作用是:自動(dòng)創(chuàng)建、更新、驗(yàn)證數(shù)據(jù)庫表結(jié)構(gòu)。該參數(shù)的幾種配置如下:
- create:每次加載hibernate時(shí)都會(huì)刪除上一次的生成的表,然后根據(jù)你的model類再重新來生成新表,哪怕兩次沒有任何改變也要這樣執(zhí)行,這就是導(dǎo)致數(shù)據(jù)庫表數(shù)據(jù)丟失的一個(gè)重要原因。
- create-drop:每次加載hibernate時(shí)根據(jù)model類生成表,但是sessionFactory一關(guān)閉,表就自動(dòng)刪除。
- update:最常用的屬性,第一次加載hibernate時(shí)根據(jù)model類會(huì)自動(dòng)建立起表的結(jié)構(gòu)(前提是先建立好數(shù)據(jù)庫),以后加載hibernate時(shí)根據(jù)model類自動(dòng)更新表結(jié)構(gòu),即使表結(jié)構(gòu)改變了但表中的行仍然存在不會(huì)刪除以前的行。要注意的是當(dāng)部署到服務(wù)器后,表結(jié)構(gòu)是不會(huì)被馬上建立起來的,是要等應(yīng)用第一次運(yùn)行起來后才會(huì)。
- validate:每次加載hibernate時(shí),驗(yàn)證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu),只會(huì)和數(shù)據(jù)庫中的表進(jìn)行比較,不會(huì)創(chuàng)建新表,但是會(huì)插入新值。
以上我們完成了基本的配置工作,記下來看一下如何進(jìn)行表與實(shí)體的映射,以及數(shù)據(jù)訪問接口。
4.3創(chuàng)建實(shí)體以及數(shù)據(jù)訪問接口
首先來看一下實(shí)體類Person.java
@Entity @Getter @Setter public class Person { @Id @GeneratedValue private Long id; @Column(name = "name", nullable = true, length = 20) private String name; @Column(name = "agee", nullable = true, length = 4) private int age; }
接著是PersonRepository.java,改接口只需要繼承JpaRepository接口即可。
public interface PersonRepository extends JpaRepository<Person, Long> { }
然后寫一個(gè)rest接口以供測(cè)試使用。
@RestController @RequestMapping(value = "person") public 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); } }
好了,讓我們來運(yùn)行一下程序看看結(jié)果吧,啟動(dòng)程序,查詢數(shù)據(jù)庫我們就可以看到,JPA以及自動(dòng)幫我們創(chuàng)建了表
接下來我們調(diào)用一下addPerson接口。我們使用postman來測(cè)試:
然后通過查詢數(shù)據(jù)庫來看一下結(jié)果:
我們可以看到成功插入了數(shù)據(jù),并且觀察表結(jié)構(gòu)可以看到,agee是我們定義的column名稱,id為自增。并且從上面的repository接口代碼我們可以看到,接口中并沒有定義任何的方法,這是因?yàn)镴paRepository中幫我們定義了基礎(chǔ)的增刪改查方法,可以很方便的直接使用。
接下來我們來看一下如何編寫自己的方法。我們以根據(jù)name查詢person為例。添加一個(gè)rest接口
@GET @Produces(TYPE_JSON) @Path("getPerson") public Object getPerson(@QueryParam("name") String name) { return personRepository.findByName(name); }
并在repository接口中添加如下查詢方法:
Person findByName(String name);
重啟之后讓我們來看一下查詢結(jié)果
我們可以看到通過name獲取到了想要的結(jié)果。我們也可以在日志中看到hibernate輸出的日志:
Hibernate: select person0_.id as id1_0_, person0_.agee as agee2_0_, person0_.name as name3_0_ from person person0_ where person0_.name=?
那么JPA是通過什么規(guī)則來根據(jù)方法名生成sql語句查詢的呢?
其實(shí)JPA在這里遵循Convention over configuration(約定大約配置)的原則,遵循spring 以及JPQL定義的方法命名。Spring提供了一套可以通過命名規(guī)則進(jìn)行查詢構(gòu)建的機(jī)制。這套機(jī)制會(huì)把方法名首先過濾一些關(guān)鍵字,比如 find…By, read…By, query…By, count…By 和 get…By 。系統(tǒng)會(huì)根據(jù)關(guān)鍵字將命名解析成2個(gè)子語句,第一個(gè) By 是區(qū)分這兩個(gè)子語句的關(guān)鍵詞。這個(gè) By 之前的子語句是查詢子語句(指明返回要查詢的對(duì)象),后面的部分是條件子語句。如果直接就是 findBy… 返回的就是定義Respository時(shí)指定的領(lǐng)域?qū)ο蠹?,同時(shí)JPQL中也定義了豐富的關(guān)鍵字:and、or、Between等等,下面我們來看一下JPQL中有哪些關(guān)鍵字:
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) |
…… |
以上就是jpa的簡單實(shí)用和介紹。
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java SpringMVC 集成靜態(tài)資源的方式你了解嗎
本篇文章主要介紹了SpringMVC集成靜態(tài)資源的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-10-10SpringBoot配置多個(gè)數(shù)據(jù)源超簡單步驟(連接多個(gè)數(shù)據(jù)庫)
公司項(xiàng)目有連接多個(gè)不同數(shù)據(jù)庫的需求,特研究了一下,根據(jù)網(wǎng)上的資料,這篇文章主要給大家介紹了關(guān)于SpringBoot配置多個(gè)數(shù)據(jù)源(連接多個(gè)數(shù)據(jù)庫)的相關(guān)資料,需要的朋友可以參考下2024-05-05Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(45)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07Spring-cloud 服務(wù)發(fā)現(xiàn)與消費(fèi)(以ribbon為例)
這篇文章主要介紹了Spring-cloud 服務(wù)發(fā)現(xiàn)與消費(fèi)(以ribbon為例),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04Java獲取兩個(gè)集合List的交集、補(bǔ)集、并集(相加)和差集(相減)的不同方式
這篇文章主要給大家介紹了關(guān)于Java獲取兩個(gè)集合List的交集、補(bǔ)集、并集(相加)和差集(相減)的不同方式,在一般操作中對(duì)于list集合取交集、差集、并集,比較簡單,需要的朋友可以參考下2023-08-08Java中的private、protected、public和default的區(qū)別(詳解)
下面小編就為大家?guī)硪黄狫ava中的private、protected、public和default的區(qū)別(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11Java Spring5學(xué)習(xí)之JdbcTemplate詳解
這篇文章主要介紹了Java Spring5學(xué)習(xí)之JdbcTemplate詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-05-05springcloud-gateway整合jwt+jcasbin實(shí)現(xiàn)權(quán)限控制的詳細(xì)過程
這篇文章主要介紹了springcloud-gateway整合jwt+jcasbin實(shí)現(xiàn)權(quán)限控制,基于springboot+springcloud+nacos的簡單分布式項(xiàng)目,項(xiàng)目交互采用openFeign框架,單獨(dú)提取出來成為一個(gè)獨(dú)立的model,需要的朋友可以參考下2023-02-02metershpere實(shí)現(xiàn)調(diào)用自定義jar包中的方法
在MeterSphere接口測(cè)試中,面對(duì)多層循環(huán)邏輯和邏輯判斷等復(fù)雜情況,直接編寫測(cè)試用例往往顯得混亂不便,本文介紹了一個(gè)簡化這一過程的方法:首先使用IDEA創(chuàng)建Maven工程,編寫所需邏輯并生成jar包;然后在MeterSphere中上傳此jar包2024-10-10