Spring Data JPA用法详解

Spring Data JPA:

JPA(Java Persistence API)即java持久化API,它的出现主要是为了简化持久层开发以及整合ORM技术,结束Hibernate、TopLink、JDO等ORM框架各自为营的局面。JPA是在吸收现有ORM框架的基础上发展而来,易于使用,伸缩性强。总的来说,JPA包括以下三方面的技术:

  • ORM映射元数据:支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系
  • API:操作实体对象来执行CRUD操作
  • 查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合

Sping Data JPA官方解释:

Spring Data JPA是Spring Data家族的一部分,可以轻松实现基于JPA的存储库。此模块处理对基于JPA的数据访问层的增强支持。它使构建使用数据访问技术的Spring驱动应用程序变得更加容易。

在相当长的一段时间内,实现应用程序的数据访问层一直很麻烦。必须编写太多样板代码来执行简单查询以及执行分页和审计。Spring Data JPA旨在减少实际需要的工作量来显著改善数据访问层的实现。

SpringBoot 整合Spring Data JPA:

导入依赖:


    org.springframework.boot
    spring-boot-starter-data-jpa

数据库配置:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/chapter05?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
#表示Jpa对应的数据库是mysql
spring.jpa.show-sql=true
#项目启动时根据实体类更新数据库中的表
spring.jpa.hibernate.ddl-auto=update

spring.jpa.hibernate.ddl-auto:

  • create:每次运行程序时,都会重新创建表,故而数据会丢失
  • create-drop:每次运行程序时会先创建表结构,然后程序结束时清空表
  • update:每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
  • validate:运行程序会校验数据于数据库的字段类型是否相同,字段不同会报错
  • none:禁用DDL处理

Spring Data JPA的使用:

创建实体类:

import lombok.Data;

import javax.persistence.*;

@Data
@Entity(name = "t_book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "book_name")
    private String name;
    @Column(name = "book_author")
    private String author;
    private Float price;
    @Transient
    private String description;
}

代码解释:

  • @Entity注解表示该类是一个实体类,在项目启动时会根据该类自动生成一张表,表的名称即@Entity注解中name的值,如果不配置name,默认表名为类名
  • 所有的实体类都要有主键,@Id注解表示该属性是一个主键,@GneeratedValue注解表示主键自动生成,strategy则表示主键的生成策略
  • 默认情况下,生成的表中字段的名称时实体类中属性的名称,通过@Column注解可以定制生成的字段的属性,name表示该属性对应的数据表中字段的名称,nullable表示该字段非空
  • @Transient注解表示在生成数据库的表时,该属性被忽略,即不生成对应的字段

JPA自带的几种主键生成策略:

  • TABLE:使用一个特定的数据库表格来保存主键
  • SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。这个值要于generator一起使用,generator指定生成主键的生成器
  • IDENTITY:主键由数据库自动生成(主要支持自动增长的数据库,如mysql)
  • AUTO:主键由程序控制,也是GenerationType的默认值

Dao层:

创建BookDao接口,继承JpaRepository,代码如下:

import com.example.demo.domain.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public interface BookDao extends JpaRepository {
    //查询以某个字符开始的所有书
    List getBooksByAuthorStartingWith(String author);
    //查询单价大于某个值的所有书
    List getBooksByPriceGreaterThan(Float price);
    @Query(value = "select * from t_book where id=(select max(id) from t_book)",nativeQuery = true)
    Book getMaxIdBook();
    @Query("select b from t_book b where b.id>:id and b.author=:author")
    List getBookByIdAndAuthor(@Param("author") String author,@Param("id") Integer id);
    @Query("select b from t_book b where b.id getBookByIdAndName(String name,Integer id);
}

代码解释:

  • 自定义BookDao继承自JpaRepositiory。JpaRepositiory中提供了一些基本的数据操作方法,有基本的增删改查、分页查询、排序查询等
  • 在Spring Data JPA中,只要方法的定义符合既定规范,Spring Data就能分析出开发者意图,从而避免开发者定义SQL

Service层:

创建BookService,代码如下:

import com.example.demo.dao.BookDao;
import com.example.demo.domain.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BookService {
    @Autowired
    BookDao bookDao;

    //save方法由JpaRepository接口提供
    public void addBook(Book book){
        bookDao.save(book);
    }

    //分页查询
    public Page getBookByPage(Pageable pageable){
        return bookDao.findAll(pageable);
    }

    public List getBooksByAuthorStartingWith(String author){
        return bookDao.getBooksByAuthorStartingWith(author);
    }

    public List getBooksByPriceGreaterThan(Float price){
        return bookDao.getBooksByPriceGreaterThan(price);
    }

    public Book getMaxIdBook(){
        return bookDao.getMaxIdBook();
    }

    public List getBookByIdAndName(String name,Integer id){
        return bookDao.getBookByIdAndName(name,id);
    }

    public List getBookByIdAndAuthor(String author,Integer id){
        return bookDao.getBookByIdAndAuthor(author,id);
    }
}

Controller层:

创建BookContrller,实现对数据的测试,代码如下:

import com.example.demo.domain.Book;
import com.example.demo.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class BookController {
    @Autowired
    BookService bookService;

    @GetMapping(value = "/findAll")
    public void findAll(){
        PageRequest pageRequest = PageRequest.of(2,3);
        Page page = bookService.getBookByPage(pageRequest);
        System.out.println("总页数:"+page.getTotalPages());
        System.out.println("总记录数:"+page.getTotalElements());
        System.out.println("查询结果:"+page.getContent());
        //从0开始记,所以加上1
        System.out.println("当前页数:"+(page.getNumber()+1));
        System.out.println("当前记录数:"+page.getNumberOfElements());
        System.out.println("每页记录数:"+page.getSize());
    }

    @GetMapping(value = "search")
    public void search(){
        List bs1 = bookService.getBookByIdAndAuthor("鲁迅",7);
        List bs2 = bookService.getBooksByAuthorStartingWith("吴");
        List bs3 = bookService.getBookByIdAndName("西",8);
        List bs4 = bookService.getBooksByPriceGreaterThan(30F);

        Book b = bookService.getMaxIdBook();
        System.out.println("bs1:"+bs1);
        System.out.println("bs2:"+bs2);
        System.out.println("bs3:"+bs3);
        System.out.println("bs4:"+bs4);
        System.out.println("b:"+b);
    }

    @GetMapping(value = "/save")
    public void save(){
        Book book = new Book();
        book.setAuthor("鲁迅");
        book.setName("呐喊");
        book.setPrice(23F);
        bookService.addBook(book);
    }
}

代码解释:

  • 在findAll接口中,首先通过调用PageRequest中的of方法构造PageRequest对象。of方法接收两个参数:第一个参数是页数,从0开始计数,第二个参数是每页显示的条数

数据库数据: 

Spring Data JPA用法详解_第1张图片

 

调用httP://127.0.0.1:8080/findAll接口:

总页数:3
总记录数:7
查询结果:[Book(id=7, name=故事新编, author=鲁迅, price=22.0, description=null)]
当前页数:3
当前记录数:1
每页记录数:3

调用httP://127.0.0.1:8080/save接口:

Hibernate: insert into t_book (book_author, book_name, price) values (?, ?, ?)

调用httP://127.0.0.1:8080/search接口:

bs1:[Book(id=8, name=呐喊, author=鲁迅, price=23.0, description=null)]
bs2:[Book(id=3, name=西游记, author=吴承恩, price=29.0, description=null)]
bs3:[Book(id=3, name=西游记, author=吴承恩, price=29.0, description=null)]
bs4:[Book(id=2, name=红楼梦, author=曹雪芹, price=35.0, description=null), Book(id=5, name=围城, author=钱钟书, price=33.0, description=null)]
b:Book(id=8, name=呐喊, author=鲁迅, price=23.0, description=null)

 

你可能感兴趣的:(springboot,spring)