百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

12《Spring Boot 入门教程》Spring Boot 使用 JPA

ccwgpt 2025-03-11 13:46 73 浏览 0 评论

1. 前言

使用 JDBC ,或者 JdbcTemplate 操作数据库,需要编写大量的 SQL 语句。SQL 语句基本都是些模板代码,实际上是可以通过分析模板代码的规则自动生成的。

JPA 就是简化 Java 持久层数据操作的技术标准,是一种方案和规范。最开始是 Sun 公司提出的, Sun 公司就是开发出 Java 的公司,一度非常厉害,结果被 Oracle 收购了。Sun 公司虽然提出了 JPA 标准,但是并没有具体实现。JPA 的实现里面比较出名的就是 Hibernate 了,所以本篇我们也是以 Hibernate 实现为基础进行 Spring Boot + JPA 的实例讲解。

本篇演示一个 Spring Boot 商品管理项目实例,其中数据持久层操作采用 JPA ,以体会 JPA 的优雅与高效。

2. JPA 基本原理

在开始实例之前,还是有必要聊聊 JPA 是如何实现的,便于大家理解。

首先是 ORM 映射,通过注解或 XML 描述对象和表直接的映射关系。例如 GoodsDo 商品类对应数据库中的 goods 商品表,商品类里面的属性和商品表里面的列一一对应,商品类的一个对象就对应商品表中的一行数据。

然后就是对数据库进行 CRUD (增删改查)操作了,由于已经配置了对象和表的映射关系,所以可以自动生成对应的 SQL 语句,然后执行语句即可。

3. 开发流程

光说不练那是假把式,我们来使用 Spring Boot + JPA 开发一个完整实例。

3.1 使用 Spring Initializr 创建项目

Spring Boot 版本选择 2.2.5 ,Group 为 com.imooc , Artifact 为 spring-boot-jpa ,生成项目后导入 Eclipse 开发环境。

3.2 引入项目依赖

我们引入 Web 项目依赖、热部署依赖。由于本项目需要使用 JPA 访问数据库,所以引入 spring-boot-starter-jdbcmysql-connector-java
spring-boot-starter-data-jpa
依赖。 pom.xml 文件中依赖项如下:

实例:

        
        
            org.springframework.boot
            spring-boot-devtools
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
        
            mysql
            mysql-connector-java
        

3.3 修改配置文件

application.properties 中添加以下配置:

实例:

# 配置数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 配置数据库url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
# 配置数据库用户名
spring.datasource.username=root
# 配置数据库密码
spring.datasource.password=Easy@0122

# 启动时更新表结构,保留数据
spring.jpa.hibernate.ddl-auto=update

此处需要注意的是
spring.jpa.hibernate.ddl-auto=update
。可以理解项目启动时,根据实体类结构更新数据库表结构,且保留数据库中的数据。

3.4 开发商品类

开发商品类 GoodsDo ,并通过注解实现类结构与数据表结构的映射。

实例:

/**
 * 商品类
 */
@Entity // 表示这是一个数据对象类
@Table(name = "goods") // 对应数据库中的goods表
public class GoodsDo {
    /**
     * 商品id
     */
    @Id // 该字段对应数据库中的列为主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增长
    @Column(name = "id") // 对应goods表中的id列
    private Long id;
    /**
     * 商品名称
     */
    @Column(name = "name") // 对应goods表中的name列
    private String name;
    /**
     * 商品价格
     */
    @Column(name = "price") // 对应goods表中的price列
    private String price;
    /**
     * 商品图片
     */
    @Column(name = "pic") // 对应goods表中的pic列
    private String pic;
    // 省略get set方法
}

3.5 开发数据操作接口

开发商品数据接口,代码如下:

实例:

/**
 * 商品数据操作接口
 */
@Repository
public interface IGoodsDao extends CrudRepository {
}

解释下,@Repository 将接口标注为数据访问层组件,该接口通过继承 CrudRepository 实现 CRUD 操作。泛型参数分别为实体类及主键的数据类型。

注意此时已经可以通过 IGoodsDao 对数据库 goods 表进行增删改查操作了。

3.6 开发服务层

开发 Goods Service ,注入 IGoodsDao 类型组件实现服务方法。

实例:

/**
 * 商品服务类
 */
@Service
public class GoodsService {
    @Autowired
    private IGoodsDao goodsDao;

    /**
     * 新增商品
     */
    public void add(GoodsDo goods) {
        goodsDao.save(goods);
    }

    /**
     * 删除商品
     */
    public void remove(Long id) {
        goodsDao.deleteById(id);
    }

    /**
     * 编辑商品信息
     */
    public void edit(GoodsDo goods) {
        goodsDao.save(goods);
    }

    /**
     * 按id获取商品信息
     */
    public Optional getById(Long id) {
        return goodsDao.findById(id);
    }

    /**
     * 获取商品信息列表
     */
    public Iterable getList() {
        return goodsDao.findAll();
    }
}

此处需要解释下 Optional 类,它是一个包装类。它的内容是空或者包含的对象,所以可以避免空指针问题。此处稍作了解即可。

3.7 开发控制器

我们还是遵循 RESTful 风格,开发控制器类。

实例:

/**
 * 商品控制器类
 */
@RestController
public class GoodsController {
    @Autowired
    private GoodsService goodsService;
    /**
     * 按id获取商品信息
     */
    @GetMapping("/goods/{id}")
    public Optional getOne(@PathVariable("id") long id) {
        return goodsService.getById(id);
    }
    /**
     * 获取商品列表
     */
    @GetMapping("/goods")
    public Iterable getList() {
        return goodsService.getList();
    }
    /**
     * 新增商品
     */
    @PostMapping("/goods")
    public void add(@RequestBody GoodsDo goods) {
        goodsService.add(goods);
    }
    /**
     * 编辑商品
     */
    @PutMapping("/goods/{id}")
    public void update(@PathVariable("id") long id, @RequestBody GoodsDo goods) {
        // 修改指定id的博客信息
        goods.setId(id);
        goodsService.edit(goods);
    }
    /**
     * 移除商品
     */
    @DeleteMapping("/goods/{id}")
    public void delete(@PathVariable("id") long id) {
        goodsService.remove(id);
    }
}

4. 测试

我们主要是测试 JPA 模块正确可用,所以直接在测试类发起对 IGoodsDao 方法的测试即可。

4.1 新增测试

首先我们建立数据库 shop ,数据库中不必有表 goods ,如果有 goods 表的话可以将它删除。因为我们设置了
spring.jpa.hibernate.ddl-auto=update
, JPA 会在项目启动时自动建立表结构。

实例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaAddTest {
    @Autowired
    private IGoodsDao goodsDao;

    /**
     * 新增测试
     */
    @Test
    public void testAdd() {
        GoodsDo goods = new GoodsDo();
        goods.setName("梨张");
        goods.setPic("梨图片");
        goods.setPrice("2.0");
        GoodsDo result = goodsDao.save(goods);
        System.out.println("新增商品id:" + result.getId());
        assertNotNull(result);
    }
}

运行测试类,控制台输出新增商品id:1,说明插入一条数据成功,且插入数据 id 为 1 。

同时查看数据库,发现已经自动构建表结构:

MySQL 数据库已自动构建表结构

4.2 修改测试

当调用 save 方法,如果给参数中 id 属性赋值,则会进行数据更新操作。

实例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaEditTest {
   @Autowired
   private IGoodsDao goodsDao;

   /**
    * 修改测试
    */
   @Test
   public void testEdit() {
    GoodsDo goods = new GoodsDo();
    goods.setId(1L);
    goods.setName("梨张");
    goods.setPic("梨图片");
    goods.setPrice("100.0");
    GoodsDo result = goodsDao.save(goods);
    assertNotNull(result);
   }
}

此时查看数据库中数据,发现金额已修改成功。

MySQL 数据库中金额修改成功

4.3 查询测试

我们进行按 id 查询、查询所有操作,并打印查询结果。

实例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaQueryTest {
   @Autowired
   private IGoodsDao goodsDao;

   /**
    * 按id查询
    */
   @Test
   public void testQueryById() {
    Optional goodsOptional = goodsDao.findById(1L);
    GoodsDo goods = goodsOptional.get();
    System.out.println(goods.getId() + "-" + goods.getName() + "-" + goods.getPic() + "-" + goods.getPrice());
   }

   /**
    * 查询全部
    */
   @Test
   public void testQueryAll() {
    Iterable goodsIt = goodsDao.findAll();
    for (GoodsDo goods : goodsIt) {
        System.out.println(goods.getId() + "-" + goods.getName() + "-" + goods.getPic() + "-" + goods.getPrice());
    }
   }
}

4.4 删除测试

指定删除 id 为 1 的商品。

实例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class JpaRemoveTest {
   @Autowired
   private IGoodsDao goodsDao;

   /**
    * 删除测试
    */
   @Test
   public void testRemove() {
    goodsDao.deleteById(1L);
   }
}

运行后,数据库中商品信息被删除,大功告成!

5. 小结

使用 JPA 后,最大的好处就是不用写 SQL 了,完全面向对象编程,简洁又省心,何乐而不为。

相关推荐

腾讯开源框架TarsCpp-rpc设计分析-server(二)

2Tars协议2.1是什么借用官方说法:TARS编码协议是一种数据编解码规则,它将整形、枚举值、字符串、序列、字典、自定义结构体等数据类型按照一定的规则编码到二进制数据流中。对端接收到二进制数据流...

微服务调用为什么用RPC框架,http不更简单吗?

简单点,HTTP是协议,RPC是概念!实现RPC可以基于HTTP协议(Feign),TCP协议(Netty),RMI协议(Soap),WebService(XML—RPC)框架。传输过程中,也因为序列...

go-zero:开箱即用的微服务框架(gin框架微服务)

go-zero是一个集成了各种工程实践的Web和rpc框架,它的弹性设计保障了大并发服务端的稳定性,并且已经经过了充分的实战检验。go-zero在设计时遵循了“工具大于约定和文档”的理...

SOFARPC :高性能、高扩展性、生产级的 Java RPC 框架

#暑期创作大赛#SOFARPC是一个高性能、高扩展性、生产级的JavaRPC框架。在蚂蚁金服,SOFARPC已经使用了十多年,已经发展了五代。SOFARPC致力于简化应用程序之间的RPC...

自研分布式高性能RPC框架及服务注册中心ApiRegistry实践笔记

痛点1.bsf底层依赖springcloud,影响bsf更新springboot新版本和整体最新技术版本升级。2.eureka已经闭源,且框架设计较重,同时引入eureka会自行引入较多sprin...

Rust语言从入门到精通系列 - Tonic RPC框架入门实战

Rust语言是一种系统级语言,被誉为“没有丧失性能的安全语言”。Rust语言的优势在于其内存安全机制,在编译时就能保证程序的内存安全。Tonic模块是Rust语言的一个RPC(RemoteProce...

腾讯开源框架TarsCpp-rpc设计分析-client(一)

前言Tars是腾讯开源的微服务平台,包含了一个高性能的rpc框架和服务治理平台,TarsCpp是其C++版本。对于以C++为主要开发语言,同时还想深入了解rpc和微服务框架具体实现的同学来说,Tars...

设计了一款TPS百万级别的分布式、高性能、可扩展的RPC框架

为啥要开发RPC框架事情是这样的,在开发这个RPC框架之前,我花费了不少时间算是对Dubbo框架彻底研究透彻了。冰河在撸透了Dubbo2.x和Dubbo3.x的源码之后,本来想给大家写一个Dubbo源...

rpc框架使用教程,超级稳定好用,大厂都在使用

rpc是什么远程调用协议如何使用导入依赖<dependency><groupId>org.apache.dubbo</groupId><art...

Layui 框架实战:动态加载 Select 与二级联动全解析

在现代Web开发中,下拉选择框(Select)是用户输入数据时不可或缺的组件。很多时候,我们需要的选项并非静态写死在HTML中,而是需要根据业务逻辑从后端动态获取。更有甚者,我们可能需要实现“...

15个能为你节省数百小时的前端设计神器,从UI库到文档生成

无论你是刚开始开发之旅的新手,还是疲于应付生产期限的资深程序员,有一个真理始终不变:正确的工具能彻底改变你的工作流程。多年来,我测试了数百个开发工具——有些实用,大多数平庸。但有一批免费网站经受住了时...

Layui与WinForm通用权限管理系统全解析

嘿,小伙伴们,今天咱们来聊聊Layui和WinForm这两个框架在通用权限管理系统中的应用。别担心,我会尽量用简单易懂的语言来讲解,保证让大家都能跟上节奏!首先说说Layui。Layui是一个前端UI...

纯Python构建精美UI!MonsterUI让前端开发效率飙升

“无需CSS知识,告别类名记忆,11行代码实现专业级卡片组件”在传统Web开发中,构建美观界面需要同时掌握HTML、CSS、JavaScript三剑客,开发者不得不在多种语言间频繁切换。即使使用Boo...

WebTUI:将终端用户界面(TUI)之美带到浏览器的CSS库

在当今Web技术飞速发展的时代,界面设计愈发复杂多样。然而,随着现代化工具的广泛使用,一些开发者开始回归极简风格,追求一种简洁而富有韵味的设计。WebTUI正是这样一款CSS库,它将经典的终...

人教版二年级下册生字描红汇总(拼音+笔顺+描红),可打印!

可定制内容,评论区留言。本次整理的为人教版二年级下册所有生字,共计300个;写字是小学阶段一项重要的基本功训练,把汉字写得正确、工整、美观,可以提高运用汉字这一交际工具的准确性和效率。对小学生进行写字...

取消回复欢迎 发表评论: