整合Spring Data JPA

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

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 步骤如下:

1. 创建数据库

创建数据库即可,不用创建表

创建数据库 jpa,如下

create database `jpa` default character set utf8;

2. 创建项目

创建 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>
  <scope>runtime</scope>
</dependency>

3. 数据库配置

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

# 数据库基本配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
# JPA 配置
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

4. 创建实体类

@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;
    @Override
    public String toString() {
        return "Book{"  
                "id="   id  
                ", name='"   name   '\''  
                ", author='"   author   '\''  
                ", price="   price  
                ", description='"   description   '\''  
                '}';
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    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;
    }
}

代码解释:

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

5. 创建 BookDao 接口

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> getBooksByIdAndName(String name, Integer id);
}

代码解释:

  • 自定义 BookDao 继承 JpaRepository 。JpaRepository 中提供了一些基本的数据库操作方法,有基本的增删改查、分页查询、排序查询等
  • getBooksByAuthorStartingWith() 方法表示查询以某个字符开始的所有的书
  • getBooksByPriceGreaterThan() 方法表示查询单价大于某个值的所有书
  • 在Spring Data JPA 中,只要方法的定义符合既定规范,Spring Data JPA 就能分析出开发者的意图,从而避免开发中定义 SQL 。 所谓的既定规范,就是一定的方法命名规则,支持的命名规则如下:

| 关键字 | 方法命名 | sql where字句 |

| — | — | — |

| And | findByNameAndPwd | where name= ? and pwd =? |

| Or | findByNameOrSex | where name= ? or sex=? |

| Is,Equals | findById,findByIdEquals | where id= ? |

| Between | findByIdBetween | where id between ? and ? |

| LessThan | findByIdLessThan | where id < ? |

| LessThanEqual | findByIdLessThanEqual | where id <= ? |

| GreaterThan | findByIdGreaterThan | where id > ? |

| GreaterThanEqual | findByIdGreaterThanEqual | where id > = ? |

| After | findByIdAfter | where id > ? |

| Before | findByIdBefore | where id < ? |

| IsNull | findByNameIsNull | where name is null |

| isNotNull,NotNull | findByNameNotNull | where name is not null |

| Like | findByNameLike | where name like ? |

| NotLike | findByNameNotLike | where name not like ? |

| StartingWith | findByNameStartingWith | where name like ‘?%’ |

| EndingWith | findByNameEndingWith | where name like ‘%?’ |

| Containing | findByNameContaining | where name like ‘%?%’ |

| OrderBy | findByIdOrderByXDesc | where id=? order by x desc |

| Not | findByNameNot | where name <> ? |

| In | findByIdIn(Collection<?> c) | where id in (?) | | NotIn | findByIdNotIn(Collection<?> c) | where id not in (?) |

| True | findByAaaTue | where aaa = true |

| False | findByAaaFalse | where aaa = false |

| IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) |

  • 既定的方法命名规则不一定满足所有的开发需求,因此 Spring Data JPA 也支持自定义 JPQL 或者原生 SQL 。getMaxIdBook() 方法表示查询id最大的书,nativeQuery = true 表示使用原生的 SQL 查询
  • getBookByIdAndAuthor() 表示根据 id 和 author 进行查询,这里使用默认的 JPQL 语句。JPQL 是一种面向对象表达式语言,可以将 SQL 语法和简单查询语句绑定在一起,使用这种语言编写的查询是可以移植的,可以被编译成所有主流数据库服务器上的 SQL 。JPQL 与原生 SQL 语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。getBookByIdAndAuthor() 方法使用 :id、:name 这种方式来进行参数绑定。注意:这里使用的列名是属性名称,而不是数据库中的列的名称。
  • getBooksByIdAndName() 方法也是自定义 JPQL 查询,不同的是传参使用 ?1、?2 这种方式。注意:方法中的参数的顺序要与参数声明的顺序一致
  • 如果 BookDao 中的方法设计修改操作,就需要添加 @Modifying 注解并添加事务

6. 创建 BookService

@Service
public class BookService {
    @Autowired
    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> getBookByIdAndAuthor(String author, Integer id) {
        return bookDao.getBookByIdAndAuthor(author, id);
    }
    public List<Book> getBooksByIdAndName(String name, Integer id) {
        return bookDao.getBooksByIdAndName(name, id);
    }
}

代码解释:

  • bookDao.save(book) 标识将对象数据保存到数据库,save 方法由 JpaRepository 接口提供
  • bookDao.findAll(pageable) 是一个分页查询,使用 findAll 方法,返回值为 Page ,该对象中包含有分页常用数据,例如总记录数,总页数、每页记录数、当前页记录数等

7. 创建 BookController

@RestController
public class BookController {
    @Autowired
    BookService bookService;
    @GetMapping("/findAll")
    public void findAll() {
        PageRequest pageable = PageRequest.of(2, 3);
        Page<Book> page = bookService.getBookByPage(pageable);
        System.out.println("总页数:" page.getTotalPages());
        System.out.println("总记录数:" page.getTotalElements());
        System.out.println("查询结果:" page.getContent());
        System.out.println("当前页数:" (page.getNumber() 1));
        System.out.println("当前页记录数:" page.getNumberOfElements());
        System.out.println("每页记录数:" page.getSize());
    }
    @GetMapping("/search")
    public void search() {
        List<Book> bs1 = bookService.getBookByIdAndAuthor("鲁迅", 7);
        List<Book> bs2 = bookService.getBooksByAuthorStartingWith("吴");
        List<Book> bs3 = bookService.getBooksByIdAndName("西", 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("/save")
    public void save() {
        Book book = new Book();
        book.setAuthor("鲁迅");
        book.setName("呐喊");
        book.setPrice(23F);
        bookService.addBook(book);
    }
}

代码解释:

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

8. 测试

启动项目,查看数据库发现 t_book 表已自动新建,添加测试数据

INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (1, '罗贯中', '三国演义', 30);
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (2, '曹雪芹', '红楼梦', 35);
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (3, '吴承恩', '西游记', 29);
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (4, '施耐庵', '水浒传', 29);
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (5, '钱钟书', '宋诗选注', 33);
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (6, '鲁迅', '朝花夕拾', 18);
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (7, '鲁迅', '故事新编', 22);

然后调用 /findAll 接口,控制台打印日志如下:

Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ limit ?, ?
总页数:3
总记录数:7
查询结果:[Book{id=7, name='故事新编', author='鲁迅', price=22.0, description='null'}]
当前页数:3
当前页记录数:1
每页记录数:3

接着调用 /save 接口 ,查看数据库表数据,如下

最后调用 /search 接口,控制台打印日志如下

Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.id>? and book0_.author=?
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.author like ? escape ?
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.id<? and (book0_.book_name like ?)
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.price>?
Hibernate: select * from t_book where id=(select max(id) from t_book)
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'}

到此这篇关于Spring Boot 整合持久层之Spring Data JPA的文章就介绍到这了,更多相关Spring Boot Spring Data JPA内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Spring Boot 整合持久层之Spring Data JPA的更多相关文章

  1. canvas中普通动效与粒子动效的实现代码示例

    canvas用于在网页上绘制图像、动画,可以将其理解为画布,在这个画布上构建想要的效果。本文详细的介绍了粒子特效,和普通动效进行对比,非常具有实用价值,需要的朋友可以参考下

  2. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. canvas学习和滤镜实现代码

    这篇文章主要介绍了canvas学习和滤镜实现代码,利用 canvas,前端人员可以很轻松地、进行图像处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. localStorage的过期时间设置的方法详解

    这篇文章主要介绍了localStorage的过期时间设置的方法详解的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. 详解HTML5 data-* 自定义属性

    这篇文章主要介绍了详解HTML5 data-* 自定义属性的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. HTML5的postMessage的使用手册

    HTML5提出了一个新的用来跨域传值的方法,即postMessage,这篇文章主要介绍了HTML5的postMessage的使用手册的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. 教你使用Canvas处理图片的方法

    本篇文章主要介绍了教你使用Canvas处理图片的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. ios – Swift语言:如何调用SecRandomCopyBytes

    从Objective-C,我可以这样做:在Swift中尝试这个时,我有以下内容:但我得到这个编译器错误:data.mutableBytes参数被拒绝,因为类型不匹配,但我无法弄清楚如何强制参数.解决方法这似乎有效:

  9. 使用Firebase iOS Swift将特定设备的通知推送到特定设备

    我非常感谢PushNotifications的帮助.我的应用聊天,用户可以直接向对方发送短信.但是如果没有PushNotifications,它就没有多大意义.它全部设置在Firebase上.如何将推送通知从特定设备发送到特定设备?

  10. ios – NSData to Data swift 3

    如何将此代码转换为使用Swift3数据?

随机推荐

  1. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  3. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  4. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  5. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  6. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  7. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  8. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  9. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Spring JdbcTemplate执行数据库操作详解

    JdbcTemplate是Spring框架自带的对JDBC操作的封装,目的是提供统一的模板方法使对数据库的操作更加方便、友好,效率也不错,这篇文章主要介绍了Spring JdbcTemplate执行数据库操作,需要的朋友可以参考下

返回
顶部