spring Data JPA

什麼是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);//刪除一個實體集合 

 

springBoot使用實例

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升序排序

總結:

    SpringDataJPASpring Data的一個子項目,經過提供基於JPARepository極大的減小了JPA做爲數據訪問方案的代碼量,僅須要編寫一個接口集成下SpringDataJPA內部定義的接口,便可完成簡單的CRUD操做。

相關文章
相關標籤/搜索