springboot 整合Spring Data JPA

112 篇文章 0 订阅

JPA(Java Persistence API)和Spring Data是两个范畴的概念。

作为一名Java EE工程师,基本都有听说过Hibernate框架。Hibernate是一个ORM框架,而JPA则是一种ORM规范,JPA和Hibernate的关系就像JDBC与JDBC驱动的关系,即JPA制定了ORM规范,而Hibernate是这些规范的实现(事实上,是先有Hibernate后有JPA,JPA规范的起草者也是Hibernate的作者),因此从功能上来说,JPA相当于Hibernate的一个子集。

Spring Data是Spring的一个子项目,致力于简化数据库访问,通过规范的方法名称来分析开发者的意图,进而减少数据库访问层的代码量。Spring Data不仅支持关系型数据库,也支持非关系型数据库。Spring Data JPA可以有效简化关系型数据库访问代码。

Spring Boot整合Spring Data JPA的步骤如下。

创建数据库

创建数据库jpa,代码如下:

create database `jpa` default character set utf8;

创建项目

创建Spring Boot项目,添加MySQL和Spring Data JPA的依赖,代码如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.9</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

数据库配置

在application.properties中配置数据库基本信息以及JPA相关配置:

server.port=8099
#Druid相关
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=UTC
spring.datasource.username=root
spring.datasource.password=mysql123
#jpa相关
#是否在控制台打印jpa执行的sql
spring.jpa.show-sql=true
#jpa的对应数据库是mysql
spring.jpa.database=mysql
#项目启动时根据实体类更新数据库中表
spring.jpa.hibernate.ddl-auto=update
#使用的数据库方言是MySQL57Dialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

这里的配置信息主要分为两大类,

第3~7行是数据库基本信息配置,

第9~16行是JPA相关配置。

其中,第10行表示是否在控制台打印JPA执行过程生成的SQL,

第12行表示JPA对应的数据库是MySQL,

第14行表示在项目启动时根据实体类更新数据库中的表(其他可选值有create、create-drop、validate、no),

第16行则表示使用的数据库方言是MySQL57Dialect。

创建实体类

创建Book实体类,代码如下:

Book.java

package com.shrimpking.pojo;


import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Transient;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/5 19:06
 *
 */
@Entity(name = "t_book")
public class Book
{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "book_name",nullable = false)
    private String name;
    private String author;
    private Float price;
    @Transient
    private String description;

    /*
     * @Entity注解表示此类是一个实例类,name表示数据库表的名称
     * @Id注解表示属性是一个主键,
     * @GeneratedValue注解表示主键是自动生成,strategy表示策略为mysql自增
     * @Column注解表示数据库表中的列名,是否为空
     * @Transient注解表示生成数据库表时,忽略此字段
     */

    public Book()
    {
    }

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getAuthor()
    {
        return author;
    }

    public void setAuthor(String author)
    {
        this.author = author;
    }

    public Float getPrice()
    {
        return price;
    }

    public void setPrice(Float price)
    {
        this.price = price;
    }

    public String getDescription()
    {
        return description;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    @Override
    public String toString()
    {
        return "Book{" + "id=" + id + ", name='" + name + '\'' + ", author='" + author + '\'' + ", price=" + price + ", description='" + description + '\'' + '}';
    }
}

代码解释:

• @Entity注解表示该类是一个实体类,在项目启动时会根据该类自动生成一张表,表的名称即@Entity注解中name的值,如果不配置name,默认表名为类名。所有的实体类都要有主键,@Id注解表示该属性是一个主键,@GeneratedValue注解表示主键自动生成,strategy则表示主键的生成策略。

• 默认情况下,生成的表中字段的名称就是实体类中属性的名称,通过@Column注解可以定制生成的字段的属性,name表示该属性对应的数据表中字段的名称,nullable表示该字段非空。

• @Transient注解表示在生成数据库中的表时,该属性被忽略,即不生成对应的字段。

创建BookDao

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

BookDao.java

package com.shrimpking.dao;

import com.shrimpking.pojo.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/5 19:21
 */
public interface BookDao extends JpaRepository<Book,Integer>
{
    /**
     * 根据作者名开头字符查询
     * @param author
     * @return
     */
    List<Book> getBooksByAuthorStartingWith(String author);

    /**
     * 根据图书价格大于多少查询
     * @param price
     * @return
     */
    List<Book> getBooksByPriceGreaterThan(Float price);

    /**
     * 查询id值最大的图书
     * nativeQuery= true表示使用原生的SQL查询。
     * @return
     */
    @Query(value="select * from t_book where id=(select max(id) from t_book)",nativeQuery = true)
    Book getMaxIdBook();

    /**
     * 根据id和作者名查询
     * 表示根据id和author进行查询,这里使用默认的JPQL语句。
     * 查询使用:id、:name这种方式来进行参数绑定。
     * 注意:这里使用的列名是属性的名称而不是数据库中列的名称。
     * @param author
     * @param id
     * @return
     */
    @Query(value = "select b from t_book b where b.id>=:id and b.author=:author")
    List<Book> getBooksByIdAndAuthor(
            @Param("author") String author,
            @Param("id") Integer id);

    /**
     * 根据id和图书名称模糊查询
     * 自定义JPQL查询,不同的是传参方式使用?1、?2这种方式。
     * 注意:方法中参数的顺序要与参数声明的顺序一致。
     * @param name
     * @param id
     * @return
     */
    @Query("select b from t_book b where b.id>=?2 and b.name like %?1%")
    List<Book> getBooksByIdAndName(String name,Integer id);
}

代码解释:

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

• 定义的方法表示查询以某个字符开始的所有书。

• 定义的方法表示查询单价大于某个值的所有书。

• 在Spring Data JPA中,只要方法的定义符合既定规范,Spring Data就能分析出开发者的意图,从而避免开发者定义SQL。所谓的既定规范,就是一定的方法命名规则。既定的方法命名规则不一定满足所有的开发需求,因此Spring Data JPA也支持自定义JPQL(Java Persistence Query Language)或者原生SQL。表示查询id最大的书,nativeQuery= true表示使用原生的SQL查询。

• 表示根据id和author进行查询,这里使用默认的JPQL语句。JPQL是一种面向对象表达式语言,可以将SQL语法和简单查询语义绑定在一起,使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。JPQL与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性(用过Hibernate的读者会觉得这类似于HQL)。查询使用:id、:name这种方式来进行参数绑定。注意:这里使用的列名是属性的名称而不是数据库中列的名称。也是自定义JPQL查询,不同的是传参方式使用?1、?2这种方式。注意:方法中参数的顺序要与参数声明的顺序一致。

• 如果BookDao中的方法涉及修改操作,就需要添加@Modifying注解并添加事务。

创建BookService

创建BookService,代码如下:

BookService.java

package com.shrimpking.service;

import com.shrimpking.dao.BookDao;
import com.shrimpking.pojo.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;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/6 10:56
 */
@Service
public class BookService
{
    @Autowired
    private BookDao bookDao;

    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> getBooksByIdAndAuthor(String author,Integer id)
    {
        return bookDao.getBooksByIdAndAuthor(author,id);
    }

    public List<Book> getBooksByIdAndName(String name,Integer id)
    {
        return bookDao.getBooksByIdAndName(name,id);
    }
}

代码解释:

• 使用save方法将对象数据保存到数据库,save方法是由JpaRepository接口提供的。

• 是一个分页查询,使用findAll方法,返回值为Page<Book>,该对象中包含有分页常用数据,例如总记录数、总页数、每页记录数、当前页记录数等。

创建BookController

创建BookController,实现对数据的测试:

BookController.java

package com.shrimpking.controller;

import com.shrimpking.pojo.Book;
import com.shrimpking.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;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/6/6 11:07
 */
@RestController
public class BookController
{
    @Autowired
    private BookService bookService;

    @GetMapping("/findAll")
    public void findAll()
    {
        //分页,第2页,每页3个
        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());
        System.out.println("当前页数:" + page.getNumber());
        System.out.println("当前页记录数" + page.getNumberOfElements());
        System.out.println("每页记录数" + page.getSize());
    }

    @GetMapping("/search")
    public void search()
    {
        List<Book> list1 = bookService.getBooksByIdAndAuthor("作者", 7);
        List<Book> list2 = bookService.getBooksByAuthorStartingWith("作");
        List<Book> list3 = bookService.getBooksByIdAndName("图书", 5);
        List<Book> list4 = bookService.getBooksByPriceGreaterThan(10f);
        Book book1 = bookService.getMaxIdBook();
        System.out.println("getBooksByIdAndAuthor" + list1);
        System.out.println("getBooksByAuthorStartingWith" + list2);
        System.out.println("getBooksByIdAndName" + list3);
        System.out.println("getBooksByPriceGreaterThan" + list4);
        System.out.println("getMaxIdBook" + book1);


    }

    @GetMapping("/save")
    public void save()
    {
        Book book = new Book();
        book.setAuthor("作者");
        book.setName("图书集");
        book.setPrice(20f);
        bookService.addBook(book);
    }

}

代码解释:

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

• 在save接口中构造一个Book对象,直接调用save方法保存起来即可。

测试

执行8次

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

虾米大王

有你的支持,我会更有动力

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

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

打赏作者

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

抵扣说明:

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

余额充值