5.开发DAO组件 -- Spring Data JPA


开发DAO组件

作用:用来访问数据库
持久化技术:Spring Data,JPA,Mybaits,jOOQ 等
Spring Boot 为常见持久化技术提供了支持。

现在使用 Spring Data JPA


Spring Data JPA

使用Spring Data JPA来访问数据库,需要再项目添加两个依赖:

1、Spring Boot Data JPA依赖,它会自动添加数据源的实现
(用 springboot 提供的能自动配置和整合的 Spring Boot Data JPA)

        <!--  添加 Spring Boot Data JPAStarter 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

2、MySQL数据库驱动依赖

        <!--  mysql数据库驱动依赖  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

只要添加 Spring Boot Data JPA 的 starter 组件依赖,Spring Boot就会为你搞定整合 spring data jpa 的一切基础配置


创建配置文件,指定连接数据库的信息

创建一个配置文件 application.properties,就放在resources包下

# 数据库 URL
spring.datasource.url=jdbc:mysql://localhost:3306/数据库名?serverTimezone=UTC
spring.datasource.username=用户名
spring.datasource.password=密码
# 指定显示sql语句
spring.jpa.show-sql=true
# 指定根据实体自动建表
spring.jpa.generate-ddl=true

因为配置文件有配置这个功能:
指定根据实体自动建表 spring.jpa.generate-ddl=true

所以我们可以通过给Book类添加JPA注解,变成实体类。


问题:Java类和实体类有什么区别?

Java类: 是通用的,可以用于实现各种功能和逻辑
实体类: 是具有特定目的的类,用于表示领域模型中的具体实体,与数据持久化和数据库操作相关。

1、持久化能力: 实体类是指具有持久化能力的类,可以通过ORM(对象关系映射)技术将其映射到数据库表中,实现对象和数据库之间的数据交互。而普通类则通常不具备持久化的能力
2、注解: 实体类通常需要使用特定的注解(如JPA的@Entity注解)来进行标记,以便在持久化过程中进行映射和管理。而普通类不需要添加这些注解。
3、数据库映射: 实体类与数据库表之间存在一一对应或一对多的关系,实体类的属性通常与数据库表的字段相对应。而普通类则不需要与数据库表进行映射。
4、CRUD操作: 实体类通常可以通过ORM框架提供的API进行数据库的增删改查操作(CRUD操作)。而普通类不具备这些数据库操作的能力。
5、规范要求: 实体类在JPA等框架中有一些规范要求,如需要无参构造函数、需要主键等。而普通类没有这些规范要求。
6、实例化和使用: ava类可以被直接实例化和使用,用于封装数据和实现业务逻辑。而实体类一般需要通过ORM框架或者其他方式来创建和管理,以便与数据库进行交互。


如何把Java类变成实体类:

实体类通常需要使用特定的注解(如JPA的@Entity注解)来进行标记和配置,以便在持久化过程中进行映射和管理。而Java类没有这些特定的持久化注解

package cn.ljh.boot.domain;

import javax.persistence.*;

//通过添加JPA注解,把这个Java类变成实体类
@Entity  //表明这个类是一个实体类
@Table(name = "book_inf") //把这个实体类映射到数据库的 book_inf 表
public class Book {

    @Id //主键id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //指定主键生成策略
    @Column(name = "book_id") //指定这个字段映射到数据库表的具体列名
    private Integer id;
    @Column(name = "book_name")
    private String name;
    @Column(name = "price")
    private double price;
    @Column(name = "author")
    private String author;


后面我把 price 价格的修饰改成 bigdecimal 修饰类型

IDEA连接mysql


把Java类改成实体类后,运行项目,发现数据库自动生成 bool_inf 这张表了,对应的列也都生成了。
在这里插入图片描述


准备工作完成后,现在开发DAO组件

是基于 Spring Data 开发DAO组件,用spring data ,既可以访问sql数据库,也可以访问nosql数据库。

让DAO接口继承CrudRepository接口

Spring Data会为继承了CrudRepository接口的DAO接口自动为它动态生成实现类,并将该实现类的实例部署在Spring容器中。
此外,Spring Data还可动态为BookDao增加很多查询方法。

Spring Data不仅可以自动生成大量的CRUD方法,也能允许用户定义自定义的查询(sql、HQL),
甚至允许用户使用最底层API(EntityManager、DataSource、Connection……)

开发Dao组件,只需要创建一个BookDao 接口,然后去继承CrudRepository接口就可以了。

在service就可以注入这个BookDao 对象来用了,这时候的bookDao因为继承了CrudRepository接口,所以本身已经集成了很多sql操作

public interface BookDao extends CrudRepository<Book,Integer> {
}

在这里插入图片描述
通过代码可以看出,注入BookDao组件依赖后,这个bookDao就集成了很多sql操作。
比如简单的 save 保存,findAll 查询所有,deleteById根据id删除数据等。


下面的代码就是正式的业务逻辑,使用的就是基于spring boot data jpa 来实现数据库的数据持久化操作


//添加这个@Service注解,springboot就可以自动扫描这个Service组件的实现类,然后把这个类部署成容器中的bean。
@Service
@Transactional //事务控制
public class BookServiceImpl implements BookService {

    //注入DAO组件,用有参构造器来注入
    private BookDao bookDao;

	//构造器
    public BookServiceImpl(BookDao bookDao){
        this.bookDao = bookDao;
    }
    //这个bookDao 因为继承了CrudRepository接口,所以本身已经集成了很多sql操作。
    
    //添加书籍的方法
    @Override
    public Integer addBook(Book book) {
        Book b = bookDao.save(book);
        return b.getId();
    }

    //查看所有书籍的方法
    @Override
    public List<Book> getAllBooks() {
        //要强制转换
        List<Book> listBooks = (List<Book>) bookDao.findAll();
        return  listBooks;
    }

    //删除书籍的方法
    @Override
    public void deleteBookById(Integer id) {
        bookDao.deleteById(id);
    }
}

对应的前端页面也贴出来。有过一些功能修改,直接贴出来记录


添加书籍页面 bookForm.html

<!DOCTYPE html>
<!-- HTML引入Thymeleaf ,导入命名空间 , 把thymeleaf的域名加进来就可以使用了-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>添加图书页面</title>
    <!--  导入 webjar 包中的 bootstrap 样式库  -->
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.6.0/css/bootstrap.css}">

</head>
<body>

<!--  class="container" :相当于类名,就是这个div模块的名字-->
<!--  class="alert alert-primary" : 警报框  -->
<div class="container">
    <div id="addBookFailTips" th:if="${tip} != null">
        <div th:text="${tip}" class="alert alert-primary" style="text-align: center">书籍添加失败显示的提示信息</div>
    </div>

    <h2>添加图书</h2>
<!--  TODO  -->
    <!--  submit提交表单的时候,就会走这个addBook方法  -->
    <form method="post" th:action="@{/addBook}">
        <div class="form-group row">
            <label for="name" class="col-sm-3 col-form-label">图书名:</label>
            <div class="col-sm-9">
                <input type="text" id="name" name="name" class="form-control" placeholder="输入图书名">
            </div>
        </div>
        <div class="form-group row">
            <label for="author" class="col-sm-3 col-form-label">作者:</label>
            <div class="col-sm-9">
                <input type="text" id="author" name="author" class="form-control" placeholder="输入作者">
            </div>
        </div>
        <div class="form-group row">
            <label for="price" class="col-sm-3 col-form-label">价格:</label>
            <div class="col-sm-9">
                <input type="text" id="price" name="price" class="form-control" placeholder="输入价格">
            </div>
        </div>
        <div class="form-group row">
            <div class="col-sm-6 text-right">
                <button id="add" type="submit" class="btn btn-primary">添加</button>
            </div>
            <div class="col-sm-1 ">
                <button type="reset" class="btn btn-danger">重置</button>
            </div>
            <div class="col-sm-3 ">
                <a th:href="@{/listBooks}">
                    <button type="button" class="btn btn-secondary" style="background-color: yellowgreen">查看书籍列表
                    </button>
                </a>
            </div>
        </div>
    </form>
</div>
<!--TODO 提示输入信息不能为空-->
<script>
    // <!-- 如果书籍添加失败,那么在提示 2 秒后设置 div 为 none 进行隐藏 -->
    // setTimeout(function() {
    //     document.getElementById("addBookFailTips").style.display = "none";
    // }, 2000); // 2秒后隐藏
</script>
</body>
</html>

书籍列表页面 listBooks.html

<!DOCTYPE html>
<!-- HTML引入Thymeleaf ,导入命名空间 , 把thymeleaf的域名加进来就可以使用了-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>书籍列表页面</title>
    <!--  导入 webjar 包中的 bootstrap 样式库  -->
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.6.0/css/bootstrap.css}">

</head>
<body>
<!--  class="container" :相当于类名,就是这个div模块的名字-->
<!--  class="alert alert-primary" : 警报框  -->
<div class="container">
    <table class="table table-hover">
        <tr>
            <th>书名</th>
            <th>价格</th>
            <th>作者</th>
            <th>删除</th>
        </tr>
        <!--  循环迭代  ${books}就是后端传来的集合数据, book就是循环后的变量  -->
        <tr th:each="book: ${books}">
            <td th:text="${book.name}">书名</td>
            <td th:text="${book.price}">价格</td>
            <td th:text="${book.author}">作者</td>
            <td><a th:href="@{/deleteBook/} + ${book.id}">删除</a></td>
        </tr>
    </table>
</div>
<div class="container">
        <a th:href="@{/bookForm}"><button type="button" style="background-color: beige">返回添加书籍</button></a>
</div>
</body>
</html>

实现页面:

bookForm页面
在这里插入图片描述


listBooks页面
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_L_J_H_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值