Spring基础分析08-集成JPA/Hibernate进行ORM操作
大家好,今天和大家一起分享一下Spring集成JPAHibernate进行ORM操作的流程~
JPA(Java Persistence API)作为Java EE标准的一部分,提供了统一的API来管理实体类和持久化上下文;Hibernate则是最流行的JPA实现之一,以其灵活性和强大功能著称。Spring框架通过其数据访问抽象层,为JPA/Hibernate提供了卓越的支持,使得ORM操作变得更加简单、直观且高效。
ORM的基本概念
对象关系映射是一种编程技术,用于在面向对象的数据模型和关系型数据库之间建立映射关系。通过ORM工具,我们可以像操作普通Java对象一样对数据库中的记录进行增删改查等操作,而不需要关心底层SQL语句的具体实现。
JPA与Hibernate
JPA是Java平台上的持久性标准,定义了一组接口和注解来描述实体类及其关系。Hibernate是JPA的一个开源实现,除了遵循JPA规范外,还提供了许多额外的功能,如二级缓存、查询语言HQL等。选择JPA或Hibernate取决于项目的具体需求和技术栈偏好。
Spring集成JPA/Hibernate的基础
Spring Data JPA是Spring Data项目的一部分,旨在简化JPA的使用。它提供了一套通用的CRUD仓库接口和查询方法,让我们可以专注于业务逻辑而不是繁琐的数据访问细节。此外,Spring Data JPA还支持自定义查询方法、分页、排序等功能,极大地提高了开发效率。
配置Spring Boot项目
为了快速开始一个新的Spring Boot项目,我们可以使用Spring Initializr生成基础代码结构。在这个过程中,选择Web、JPA、Thymeleaf(或其他模板引擎)、H2(内存数据库)等依赖项。接下来,在application.properties文件中配置数据库连接信息:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
对于实际生产环境,建议使用MySQL、PostgreSQL等外部数据库,并相应调整配置参数。
实体类定义
基本注解
在定义实体类时,我们需要使用一系列JPA注解来描述实体属性及其与数据库表字段之间的映射关系。以下是几个常用的注解:
- @Entity:标记一个类为JPA实体。
- @Table:指定实体对应的数据库表名(可选,默认与类名相同)。
- @Id:标识主键字段。
- @GeneratedValue:指定主键生成策略(如自增、UUID等)。
- @Column:定义列名、长度、是否允许为空等属性。
- @Temporal:用于日期时间类型的字段,指定存储格式(如TIMESTAMP、DATE等)。
@Entity
@Table(name = "users")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false, length = 50)private String username;@Column(nullable = false, length = 100)private String email;// Getters and Setters...
}
关联映射
当涉及到多个实体之间的关联时,可以使用以下注解来描述一对多、多对一、多对多等关系:
- @ManyToOne 和 @OneToMany
- @ManyToMany
- @JoinColumn:定义外键约束。
- @JoinTable:用于多对多关系,指定中间表及其关联字段。
@Entity
public class Post {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "user_id", nullable = false)private User author;@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)private List<Comment> comments = new ArrayList<>();// Getters and Setters...
}@Entity
public class Comment {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "post_id", nullable = false)private Post post;private String content;// Getters and Setters...
}
仓库接口
CRUD操作
Spring Data JPA提供了一个名为CrudRepository的基础接口,其中包含了基本的CRUD方法。我们只需要继承这个接口并为每个实体创建相应的仓库接口即可。
public interface UserRepository extends CrudRepository<User, Long> {// Additional custom query methods can be added here.
}
自定义查询方法
除了默认的CRUD方法外,还可以通过命名约定或JPQL/QueryDSL等方式定义自定义查询方法。例如:
public interface UserRepository extends CrudRepository<User, Long> {List<User> findByUsername(String username);@Query("SELECT u FROM User u WHERE u.email LIKE %?1%")List<User> findByEmailLike(String email);
}
事务管理
声明式事务管理
Spring提供了声明式事务管理机制,通过@Transactional注解可以轻松地为服务层方法添加事务支持。如果方法执行期间发生异常,整个事务将会回滚,保证了数据的一致性。
@Service
@Transactional
public class UserService {private final UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}public void createUser(User user) {userRepository.save(user);}
}
编程式事务管理
对于一些复杂的场景,比如需要在一个方法中多次开始和结束事务,编程式事务管理提供了更大的灵活性。
@Autowired
private PlatformTransactionManager transactionManager;public void complexOperation() {DefaultTransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// Perform operations...transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);throw e;}
}
分页与排序
Spring Data JPA内置了对分页和排序的支持,只需在查询方法签名中添加Pageable参数即可。
public interface UserRepository extends CrudRepository<User, Long> {Page<User> findAll(Pageable pageable);Page<User> findByUsername(String username, Pageable pageable);
}
调用时可以通过PageRequest.of(pageNumber, pageSize)构造分页请求对象,并传入排序规则。
Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "username"));
Page<User> users = userRepository.findAll(pageable);
性能优化
批量操作
批量插入、更新或删除可以显著提高数据库操作的性能。Hibernate提供了saveOrUpdateAll()、deleteAllInBatch()等方法来支持批量操作。
List<User> users = Arrays.asList(new User("Alice"),new User("Bob"),new User("Charlie")
);
userRepository.saveAll(users);
查询缓存
启用查询缓存可以在一定程度上减少重复查询带来的性能开销。需要注意的是,查询缓存只适用于只读查询,并且可能会增加内存消耗。
@Cacheable(value = "users")
public List<User> findUsersByRole(@Param("role") String role) {return userRepository.findByRole(role);
}
继承策略
JPA支持三种继承映射策略:单表(Single Table)、表每类(Table Per Class)和联合表(Joined Table)。选择合适的策略取决于实体之间的关系和查询模式。
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type")
public abstract class User {// Common fields...
}@Entity
@DiscriminatorValue("admin")
public class Admin extends User {// Admin-specific fields...
}@Entity
@DiscriminatorValue("customer")
public class Customer extends User {// Customer-specific fields...
}
多租户支持
多租户架构允许多个客户共享同一套应用程序实例,但数据彼此隔离。Hibernate提供了两种方式来实现多租户:辨别器(Discriminator)和方案(Schema)。
@Configuration
@EnableTransactionManagement
public class HibernateConfig {@Beanpublic MultiTenantConnectionProvider multiTenantConnectionProvider() {return new MultiTenantConnectionProviderImpl();}@Beanpublic CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {return new CurrentTenantIdentifierResolverImpl();}
}
代码举例:
构建一个简单的博客系统,包含用户、帖子和评论三个实体。首先,按照前面所述步骤创建Spring Boot项目,并定义相应的实体类和仓库接口。然后,编写控制器和服务层代码来处理HTTP请求和业务逻辑。
控制器
@RestController
@RequestMapping("/api/users")
public class UserController {private final UserService userService;public UserController(UserService userService) {this.userService = userService;}@GetMappingpublic ResponseEntity<List<User>> getAllUsers() {return ResponseEntity.ok(userService.getAllUsers());}@PostMappingpublic ResponseEntity<User> createUser(@RequestBody User user) {return ResponseEntity.status(HttpStatus.CREATED).body(userService.createUser(user));}
}
服务层
@Service
@Transactional
public class UserService {private final UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}public List<User> getAllUsers() {return userRepository.findAll();}public User createUser(User user) {return userRepository.save(user);}
}
启动应用程序后,可以通过Postman或浏览器访问API端点进行测试。
最佳实践与注意事项
- 保持实体类轻量化:避免在实体类中加入过多业务逻辑,尽量将其放在服务层中处理。
- 合理使用懒加载:对于关联关系,默认采用懒加载方式可以有效减少不必要的查询次数。
- 注意并发控制:在高并发环境下,考虑使用乐观锁或悲观锁机制来防止数据竞争问题。
- 充分利用缓存:适当启用查询缓存和二级缓存,可以显著提升读取性能。
- 定期清理过期数据:对于历史数据较多的应用,建议定期归档或删除不再需要的数据,以维护数据库健康状态。
通过Spring集成JPA/Hibernate进行ORM操作,不仅可以简化数据访问层的实现,还能充分发挥两者的优势,满足复杂的企业级应用需求,欢迎大家一起沟通交流~
相关文章:

Spring基础分析08-集成JPA/Hibernate进行ORM操作
大家好,今天和大家一起分享一下Spring集成JPAHibernate进行ORM操作的流程~ JPA(Java Persistence API)作为Java EE标准的一部分,提供了统一的API来管理实体类和持久化上下文;Hibernate则是最流行的JPA实现之一&#x…...

MySQL知识汇总(一)
一些命令行操作注意加 分号 “ ; ” show databases 查看所有数据库 use 数据库名 切换数据库 show tables 查看数据库中所有表 describe 表名 显示表中所有信息 create database [if not exists] 新库名 创…...

PDFMathTranslate 一个基于AI优秀的PDF论文翻译工具
PDFMathTranslate 是一个设想中的工具,旨在翻译PDF文档中的数学内容。以下是这个工具的主要特点和使用方法: 链接:https://www.modelscope.cn/studios/AI-ModelScope/PDFMathTranslate 功能特点 数学公式识别:利用先进的OCR&…...

React+Vite从零搭建项目及配置详解
相信很多React初学者第一次搭建自己的项目,搭建时会无从下手,本篇适合快速实现功能,熟悉React项目搭建流程。 目录 一、创建项目react-item 二、调整项目目录结构 三、使用scss预处理器 四、组件库Ant Design 五、配置基础路由 六、配置…...

@pytest.fixture() 跟 @pytest.fixture有区别吗?
在iOS UI 自动化工程里面最早我用的是pytest.fixture(),因为在pycharm中联想出来的fixture是带()的,后来偶然一次我没有带()发现也没有问题,于是详细查了一下pytest.fixture() 和 pytest.fixtur…...

Google Cloud Architect 认证考试错题集5
Google Cloud Architect 认证考试错题集5 D. Store static content such as HTML and images in a Cloud Storage bucket. Use Cloud Functions to host the APIs and save the user data in Firestore. - Storing static content in a Cloud Storage bucket is a cost-effecti…...

【Maven】基础(一)
【Maven】基础一 1. 虽然工作有段时间了,但是深感maven了解的不深入,所以这次开始深入的学习。 课程地址: https://www.bilibili.com/video/BV1JN411G7gX?spm_id_from333.788.player.switch&vd_source240d9002f7c7e3da63cd9a975639409a&p2 1.…...

多模态抽取图片信息的 Prompt
多模态抽取图片信息的 Prompt 1. 中文版2. 日文版3. 英文原版 下面使用多模态从图片中抽取文章,表格,Flowcharts的Prompt。 1. 中文版 你是一位擅长提取图片、图表、文本并对其进行解释的专家,能够保持原始语言不变。## 指南- 针对输入内容…...

WPF 使用LibVLCSharp.WPF实现视频播放、停止、暂停功能
使用LibVLCSharp.WPF实现视频播放、停止、暂停功能 1, NuGet 添加 VideoLAN.LibVLC.Windows 2. NuGet 添加 LibVLCSharp.WPF 3. wpf 代码如下: <Grid ><Grid.RowDefinitions><RowDefinition Height"*" /><RowDefinition Height&q…...

Java全栈项目 - 校园招聘信息平台
项目介绍 校园招聘信息平台是一个面向高校学生和企业的双向服务平台。该系统帮助企业发布招聘信息,方便学生查询职位并投递简历,同时为学校就业部门提供就业数据分析功能。 技术栈 后端 Spring Boot 2.xSpring SecurityMyBatis PlusMySQL 8.0RedisRabbitMQ 前端 Vue.js 2…...

java导出
请求头获取responseimport com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet;PostMapping("excel/export") ApiOperation(value "党员档案导出", httpMethod "POST")…...

【嵌入式系统】期末试题库,ARM处理器,CortexM3内核,USART,EXTI,GPIO
关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...

arcgisPro相接多个面要素转出为完整独立线要素
1、使用【面转线】工具,并取消勾选“识别和存储面邻域信息”,如下: 2、得到的线要素,如下:...

QTday1
#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//设置窗口标题this->setWindowTitle("向日葵远程控制");//设置窗口图标this->setWindowIcon(QIcon("C:\\Users\\Hasee\\Desktop\\pictrue\\mypicture\\logo.png&…...

SAP ALV选择列排序时弹出定义排序顺序窗口问题
需求场景 使用REUSE_ALV_GRID_DISPLAY_LVC生成ALV,发现一个问题:使用it_events的时候选择列排序时会弹出定义排序顺序窗口,如下图所示。(正常选择某一列再使用排序功能时会直接排序,不用再选择列) CLASS l…...

CSS Backgrounds(背景)
CSS Backgrounds(背景) Introduction(介绍) CSS backgrounds play a crucial role in web design, allowing developers to apply colors, images, and other decorative elements to the background of HTML elements. This enhances the visual appeal of web pages and he…...

欧拉计划 Project Euler 27 题解
欧拉计划 Problem 27 题解 题干思路code 题干 思路 可以先筛1e6的素数出来然后暴力找即可,具体思路看代码 code #include <bits/stdc.h>using namespace std;using ll long long;const int N 1e6 5; bool vis[N]; int pri[N];void getPrime() {memset(v…...

迁移学习--fasttext概述
迁移学习 1、fasttext概述 作为NLP工程领域常用的工具包, fasttext有两大作用:进行文本分类、训练词向量 正如它的名字, 在保持较高精度的情况下, 快速的进行训练和预测是fasttext的最大优势。fasttext工具包中内含的fasttext模型具有十分简单的网络结构。使用fa…...

【数字信号处理】数字信号处理试题及答案,离散序列,Z变换,傅里叶变换
关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...

CNN、RNN、LSTM和Transformer之间的区别和联系
文章目录 CNN、RNN、LSTM和Transformer之间的区别和联系前言CNN(卷积神经网络)RNN(循环神经网络)LSTM(长短期记忆网络)Transformer四者之间的联系与区别Yolo算法简介Yolo和CNN的关系YOLO各版本 CNN、RNN、L…...

springboot448教学辅助系统(论文+源码)_kaic
摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱,出错率高,信息安全性差&#x…...

用QT制作的倒计时软件
一、pro代码 RC_ICONS countdown.ico 二、mainwindow.cpp代码 #include "mainwindow.h" #include "ui_mainwindow.h"#include <QDateTime> #include <QMessageBox> #include <QSettings>MainWindow::MainWindow(QWidget *parent): QM…...

基于 mzt-biz-log 实现接口调用日志记录
🎯导读:mzt-biz-log 是一个用于记录操作日志的通用组件,旨在追踪系统中“谁”在“何时”对“何事”执行了“何种操作”。该组件通过简单的注解配置,如 LogRecord,即可实现接口调用的日志记录,支持成功与失败…...

docker容器的安装以及用法
1、了解docker 1.1、docker是什么 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现…...

Java中的Consumer接口应该如何使用(通俗易懂图解)
应用场景: 第一次程序员A写好了个基础的遍历方法: public class Demo1 {public static void main(String[] args) {//假设main方法为程序员B写的,此时需要去调用A写好的一个遍历方法//1.如果此时B突然发现想将字符串以小写的形式打印出来,则…...

D102【python 接口自动化学习】- pytest进阶之fixture用法
day102 pytest的usefixtures方法 学习日期:20241219 学习目标:pytest基础用法 -- pytest的usefixtures方法 学习笔记: fixture调用方法 实际应用 总结 pytest.mark.usefixtures(func),pytest的usefixtures方法,无…...

从零玩转CanMV-K230(4)-小核Linux驱动开发参考
前言 K230 芯片是一款基于 RISC-V 架构的端侧 AIoT 芯片,包含两个核心: CPU 1: RISC-V 处理器,1.6GHz,32KB I-cache, 32KB D-cache, 256KB L2 Cache,128bit RVV 1.0扩展 CPU 0: RISC-V 处理器,0.8GHz&am…...

上汽大通汽车CAN数据解析开发服务及技术商用领域详细解析
上汽大通G90是一款集豪华、科技与舒适于一身的中大型MPV,号称“国产埃尔法”。在国内市场,作为“卷王”的G90主要面向中大型MPV市场,满足家庭出行、商务接待和客运租赁等多元化场景需求,在国内市场上取得了不错的销售成绩。在海外…...

基于SCUI的后台管理系统
一、SCUI Admin 官方地址:https://python-abc.xyz/scui-doc/ 高性能中后台前端解决方案,基于 Vue3、elementPlus 持续性的提供独家组件和丰富的业务模板帮助你快速搭建企业级中后台前端任务。 预览地址:https://python-abc.xyz/scui-doc/de…...

使用频谱分析仪:RBW,Res BW,分辨率带宽;Sweep,扫描;noise floor,底噪,如何降低底噪?
RBW与Sweep的定义及其特性阐述: Res BW,即Resolution Bandwidth(分辨率带宽),是衡量仪器分辨信号细节能力的重要参数。当RBW的数值越小,意味着像素点的尺寸更为精细,从而能够观察到更为细微的信…...