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:

导入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

数据库配置:

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<Book,Integer> {
    //查询以某个字符开始的所有书
    List<Book> getBooksByAuthorStartingWith(String author);
    //查询单价大于某个值的所有书
    List<Book> 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<Book> getBookByIdAndAuthor(@Param("author") String author,@Param("id") Integer id);
    @Query("select b from t_book b where b.id<?2 and b.name like %?1%")
    List<Book> getBookByIdAndName(String name,Integer id);
}

代码解释:

自定义BookDao继承自JpaRepositiory。JpaRepositiory中提供了一些基本的数据操作方法,有基本的增删改查、分页查询、排序查询等

在Spring Data JPA中,只要方法的定义符合既定规范,Spring Data就能分析出开发者意图,从而避免开发者定义SQL

Service层:

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<Book> getBookByPage(Pageable pageable){
        return bookDao.findAll(pageable);
    }
 
    public List<Book> getBooksByAuthorStartingWith(String author){
        return bookDao.getBooksByAuthorStartingWith(author);
    }
 
    public List<Book> getBooksByPriceGreaterThan(Float price){
        return bookDao.getBooksByPriceGreaterThan(price);
    }
 
    public Book getMaxIdBook(){
        return bookDao.getMaxIdBook();
    }
 
    public List<Book> getBookByIdAndName(String name,Integer id){
        return bookDao.getBookByIdAndName(name,id);
    }
 
    public List<Book> 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<Book> 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<Book> bs1 = bookService.getBookByIdAndAuthor("鲁迅",7);
        List<Book> bs2 = bookService.getBooksByAuthorStartingWith("吴");
        List<Book> bs3 = bookService.getBookByIdAndName("西",8);
        List<Book> 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开始计数,第二个参数是每页显示的条数

分页

   @Override
    public List<Person> findAllPerson(String name, Integer currentPage, Integer pagesize) {
        Pageable page = PageRequest.of(currentPage - 1, pagesize);
        if(name==null || "".equals(name))
            return personRepository.findAll(page).getContent();
        return personRepository.findAllByName(name,page);
    }
@Repository
public interface PersonRepository extends JpaRepository<Person,Integer> {
    @Query(value = "select * from persion where name like %?1%",nativeQuery = true)
    List<Person> findAllByName(String name, Pageable page);

    @Query(value = "select * from persion where id = ?1",nativeQuery = true)
    Person findByyid(Integer id);

    @Modifying
    @Transactional
    @Query(value = "delete from persion where id in (?1)",nativeQuery = true)
    void delall(String[] isd);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java资料站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值