什麼是JPA?java
全稱Java Persistence API,能夠經過註解或者XML描述【對象-關係表】之間的映射關係,並將實體對象持久化到數據庫中。mysql
爲咱們提供了:spring
1)ORM映射元數據:JPA支持XML和註解兩種元數據的形式,元數據描述對象和表之間的映射關係,框架據此將實體對象持久化到數據庫表中;sql
如:@Entity、@Table、@Column、@Transient等註解。數據庫
2)JPA 的API:用來操做實體對象,執行CRUD操做,框架在後臺替咱們完成全部的事情,開發者從繁瑣的JDBC和SQL代碼中解脫出來。緩存
如:entityManager.merge(T t);app
3)JPQL查詢語言:經過面向對象而非面向數據庫的查詢語言查詢數據,避免程序的SQL語句緊密耦合。框架
如:from Student s where s.name = ?dom
JPA僅僅是一種規範,也就是說JPA僅僅定義了一些接口,而接口是須要實現才能工做的。因此底層須要某種實現,而Hibernate就是實現了JPA接口的ORM框架。spring-boot
也就是說:
JPA是一套ORM規範,Hibernate實現了JPA規範:
什麼是spring data jpa?
spirng data jpa是spring提供的一套簡化JPA開發的框架,按照約定好的【方法命名規則】寫dao層接口,就能夠在不寫接口實現的狀況下,實現對數據庫的訪問和操做。同時提供了不少除了CRUD以外的功能,如分頁、排序、複雜查詢等等。
Spring Data JPA 能夠理解爲 JPA 規範的再次封裝抽象,底層仍是使用了 Hibernate 的 JPA 技術實現。如圖:
接口約定命名規則:
CrudRepository接口:提供了最基本的對實體類的添刪改查操做
T save(T entity);//存放單個實體
Iterable<T> save(Iterable<? extends T> entities);//保存集合
T findOne(ID id);//根據id查找實體
boolean exists(ID id);//根據id判斷實體是否存在
Iterable<T> findAll();//查詢全部實體,不用或慎用!
long count();//查詢實體數量
void delete(ID id);//根據Id刪除實體
void delete(T entity);//刪除一個實體
void delete(Iterable<? extends T> entities);//刪除一個實體的集合
void deleteAll();//刪除全部實體
PagingAndSortingRepository接口:提供了分頁與排序的功能:
Iterable<T> findAll(Sort sort); //排序
Page<T> findAll(Pageable pageable); //分頁查詢(含排序功能)
JpaRepository接口:提供了JPA的相關功能:
List<T> findAll(); //查找全部實體
List<T> findAll(Sort sort); //排序、查找全部實體
List<T> save(Iterable<? extends T> entities);//保存集合
void flush();//執行緩存與數據庫同步
T saveAndFlush(T entity);//強制執行持久化
void deleteInBatch(Iterable<T> entities);//刪除一個實體集合
1.pom添加依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
2.實體類User添加註解:
package com.example.domain; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQuery; @Entity //@NamedQuery:在Repository接口定義的findByName方法不使用默認的查詢實現,而是使用自定義查詢語句去查詢 //不標註,則使用默認實現 @NamedQuery(name = "User.findByName", query = "select name,address from User u where u.name=?1") public class User implements Serializable{ private static final long serialVersionUID = 1L; //主鍵 @Id long id; //對應數據庫字段的列名 @Column(name = "name") String name; @Column(name = "address") String address; public long getId(){ return id; } public void setId(long id){ this.id = id; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public String getAddress(){ return address; } public void setAddress(String address){ this.address = address; } }
3.編寫Repository接口(dao層)
package com.example.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.example.domain.User; public interface UserJpaRepository extends JpaRepository<User,Long> { }
這裏的UserJpaRepository接口實現了JpaRepository接口。JpaRepository實現了PagingAndSortingRepository接口,PagingAndSortingRepository接口實現了CrudRepository接口,CrudRepository接口實現了Repository接口。
Repository接口是一個標識接口,裏面是空的;
CrudRepository接口定義了增刪改查方法;
PagingAndSortingRepository接口用於分頁和排序;
因爲JpaRepository接口繼承了以上全部接口,因此擁有它們聲明的全部方法;
可是使用過程當中仍是須要注意:以findAll方法爲例,JpaRepository接口返回的是List,而PagingAndSortingRepository和CrudRepository返回的是迭代器;
UserRepository:
package com.example.repository; import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import org.springframework.data.repository.query.Param; import com.example.domain.User; public interface UserRepository extends Repository<User, Long>{ List<User> findByNameAndAddress(String name, String address); @Query(value = "from User u where u.name=:name") List<User> findByName1(@Param("name") String name); @Query(value = "select * from #{#entityName} u where u.name=?1", nativeQuery = true) List<User> findByName2(String name); List<User> findByName(String name); }
UserRepository接口主要定義了一些查詢方法;
findByNameAndAddress方法:無需額外定義其查詢語句就能直接執行。由於Spring Data Jpa會根據實體類的屬性名字以及方法名自動實現該方法;
findByName方法:因爲實體類中聲明瞭@NamedQuery註解,則使用@NamedQuery註解標註的查詢語句去查詢;
@Query用來配置自定義SQL的註解。參數nativeQuery = true代表使用原生sql,若是不配置,默認是false,則使用HQL查詢。
findByName1方法:使用了HQL語句查詢;
findByName2方法:使用了原始的sql語句查詢。
4.配置數據庫配置:
application.properties:
spring.jpa.show-sql = true logging.level.org.springframework.data=DEBUG spring.jpa.hibernate.ddl-auto= spring.datasource.url=jdbc:mysql://localhost:3306/demo spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver
5.controller、service編寫和普通項目同樣
@Query配合@Modifying使用:
@Query註解單獨使用:只能用來查詢的;配合@Modifying註解一塊兒使用,則能夠完成數據的刪除、添加、更新操做。
須要注意,此處還須要使用事務註解進行事務管理,不然會拋出TranscationRequiredException異常。
即加上@Transactional註解便可。
UserRepository:
Page<Person> findByNameAndPassword(String name ,String password,Pageable pageable);
service層:
Page<Person> p1 = personRepository.findByNameAndPassword("張三","123", new PageRequest(1,10,new Sort("id")));
List<Person> list=p1.getContent();
UserRepository:
List<Person> findByNameAndPassword(String name ,String password,Sort sort);
service層:
List<Person> p1 = personRepository.findByNameAndPassword("張三","123",new Sort(Sort.Direction.ASC,"id"));//根據Id升序排序
SpringDataJPA是Spring Data的一個子項目,經過提供基於JPA的Repository極大的減小了JPA做爲數據訪問方案的代碼量,僅須要編寫一個接口集成下SpringDataJPA內部定義的接口,便可完成簡單的CRUD操做。