Spring 核心技术解析【纯干货版】- X:Spring 数据访问模块 Spring-Orm 模块精讲

在现代 Java 企业级开发中,对象关系映射(ORM)已成为处理数据库操作的主流方式。Spring ORM 模块作为 Spring 框架的重要组成部分,为开发者提供了便捷、高效的 ORM 框架集成方案。它不仅支持 Hibernate、JPA 等主流 ORM 框架,还提供了统一的事务管理、异常转换和数据源管理,使数据库操作更加简单和规范。

本篇文章深入解析了 Spring ORM 的核心概念、依赖关系、作用及应用场景,并通过详细的示例展示了如何集成 Hibernate 进行数据库操作。无论你是刚接触 Spring ORM 的初学者,还是希望深入优化数据访问层的开发者,都可以从本篇文章中获得实用的技术指导。


文章目录

      • 1、Spring-Orm 模块介绍
        • 1.1、Spring-Orm 模块概述
        • 1.2、Spring-Orm 模块依赖
        • 1.3、Spring-Orm 模块作用
      • 2、Spring ORM 集成 Hibernate 并进行数据库操作的示例
        • 2.1、项目环境
        • 2.2、引入 Maven 依赖
        • 2.3、配置 Hibernate 的 SessionFactory
        • 2.4、定义实体类
        • 2.5、创建 DAO(数据访问对象)
        • 2.6、创建 Service 业务层
        • 2.7、测试 Service
        • 2.8、Spring ORM 在此示例中的作用
      • 3、使用 Spring-Orm 常见问题与解决方案
        • 3.1、N+1 问题
        • 3.2、事务失效
      • X、后记


1、Spring-Orm 模块介绍

1.1、Spring-Orm 模块概述

Spring-ORM 模块,是一个致力于整合对象关系映射(ORM)技术的模块,特别 适用于与 Hibernate、JPA(Java Persistence API)等流行 的ORM 框架的集成。

Spring-ORM 模块提供了 SessionFactory 的配置、事务管理以及对实体类的生命周期管理等功能,使得在 Spring 应用中使用 ORM 工具变得更加简单和高效。通过 Spring-ORM,可以利用 Spring 的事务管理能力的同时享受 ORM 框架带来的对象关系映射便利。

1.2、Spring-Orm 模块依赖

Spring-Tx 模块的依赖有四个,分别是 Spring-Beans、Spring-Core 模块、Spring-Tx 模块 和 Spirng-Jdbc 模块。

其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。而 Spring Tx 模块,是 Spring 中处理事务管理的模块。

Spring JDBC 模块,是一个提供了对 JDBC 访问的高度抽象的模块,它简化了使用 JDBC 进行数据库操作的过程。

1.3、Spring-Orm 模块作用

Spring ORM(Object-Relational Mapping)模块的作用是简化对象与关系型数据库之间的映射和交互。它为开发者提供了一种更高效、灵活的方式来处理数据库操作,支持多个主流的 ORM 框架,比如 Hibernate、JPA、JDO 等。

具体功能包括:

  1. 集成 ORM 框架:Spring ORM 模块能够与多种 ORM 框架(如 Hibernate、JPA)无缝集成,简化配置过程,减少开发者的手动配置工作。
  2. 事务管理:Spring ORM 提供统一的事务管理机制,可以通过 Spring 的声明式事务管理来简化事务的控制,减少复杂的事务处理代码。
  3. 异常转换:Spring ORM 会将 ORM 框架抛出的特定异常(如 HibernateException)转换为 Spring 的统一数据访问异常(如 DataAccessException),使异常处理变得更简洁且跨框架兼容。
  4. 数据源管理:Spring ORM 提供了灵活的数据源管理方式,可以轻松管理数据库连接和资源,支持多种数据源和数据库连接池的配置。
  5. 简化配置:通过 Spring 的依赖注入(DI)和面向切面编程(AOP),Spring ORM 可以简化 ORM 框架的配置和事务管理。

2、Spring ORM 集成 Hibernate 并进行数据库操作的示例

2.1、项目环境
  • Spring Framework 5.x / 6.x
  • Hibernate 5.x / 6.x
  • Spring ORM
  • MySQL / H2 数据库
  • Maven
2.2、引入 Maven 依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.39</version>
        </dependency>
        <!-- Spring ORM -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.3.39</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.39</version>
        </dependency>
        <!-- Hibernate Core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.6.15.Final</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
    </dependencies>
2.3、配置 Hibernate 的 SessionFactory
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
public class HibernateConfig {

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan("com.example.model"); // 实体类所在包
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        properties.put("hibernate.hbm2ddl.auto", "update"); // 自动更新表结构
        properties.put("hibernate.show_sql", "true"); // 控制台显示 SQL 语句
        return properties;
    }

    @Bean
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
        return new HibernateTransactionManager(sessionFactory);
    }
}
2.4、定义实体类
import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "email")
    private String email;

    public User() {}

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getters and Setters
}
2.5、创建 DAO(数据访问对象)
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Repository
public class UserDao {

    @Autowired
    private SessionFactory sessionFactory;

    public void saveUser(User user) {
        Session session = sessionFactory.getCurrentSession();
        session.save(user);
    }

    public User getUserById(Long id) {
        Session session = sessionFactory.getCurrentSession();
        return session.get(User.class, id);
    }

    public List<User> getAllUsers() {
        Session session = sessionFactory.getCurrentSession();
        return session.createQuery("from User", User.class).list();
    }
}
2.6、创建 Service 业务层
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
@Transactional
public class UserService {

    @Autowired
    private UserDao userDao;

    public void createUser(String name, String email) {
        User user = new User(name, email);
        userDao.saveUser(user);
    }

    public User findUserById(Long id) {
        return userDao.getUserById(id);
    }

    public List<User> getAllUsers() {
        return userDao.getAllUsers();
    }
}
2.7、测试 Service
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HibernateConfig.class);
        UserService userService = context.getBean(UserService.class);

        // 创建用户
        userService.createUser("张三", "zhangsan@example.com");

        // 查询用户
        User user = userService.findUserById(1L);
        System.out.println("用户信息:" + user.getName() + ", " + user.getEmail());

        // 查询所有用户
        userService.getAllUsers().forEach(u -> System.out.println(u.getName() + " - " + u.getEmail()));

        context.close();
    }
}
2.8、Spring ORM 在此示例中的作用

Spring ORM 通过整合 Hibernate,提供了一种简洁、规范的方式来处理数据库操作,减少了 Hibernate 的模板代码,增强事务控制,并且降低了与 Hibernate 的耦合度。如果以后切换到 JPA 或其他 ORM 框架,Spring ORM 依然可以无缝支持。

Spring ORM 在此示例中的作用:

  1. 集成 Hibernate:使用 LocalSessionFactoryBean 作为 Hibernate SessionFactory 的工厂,Spring 通过它管理 Hibernate 的会话。
  2. 事务管理:使用 HibernateTransactionManager 统一管理数据库事务,使 @Transactional 方法中的操作自动开启和提交事务。
  3. 简化 Session 管理:sessionFactory.getCurrentSession() 由 Spring 事务管理自动提供,避免手动开启和关闭 Session
  4. 简化 DAO 层开发:使用 @Repository 使 DAO 组件化,并支持自动注入 SessionFactory,避免繁琐的 Hibernate 配置。
  5. 异常转换:Spring ORM 自动将 Hibernate 的异常转换为 Spring 统一的数据访问异常,使异常处理更一致。

3、使用 Spring-Orm 常见问题与解决方案

3.1、N+1 问题

在使用 ORM 框架时,N+1 问题是一个常见的性能问题。这个问题通常发生在一对多或多对多关联查询时,ORM 框架会发送多条 SQL 语句,导致性能下降。解决 N+1 问题的方式是使用 fetch 策略:

@OneToMany(fetch = FetchType.LAZY)
private List<Order> orders;

将关联实体的抓取策略设置为 LAZY(懒加载),避免不必要的关联查询。

3.2、事务失效

在某些情况下,事务可能会失效。常见的原因有:

  • 方法的 @Transactional 注解未生效,因为 Spring 的事务管理依赖于 AOP 代理,因此必须通过 Spring 容器管理的代理对象调用事务方法。
  • 将事务方法标记为 private,Spring AOP 无法拦截 private 方法。

X、后记

Spring ORM 作为 Spring 数据访问层的重要组件,在简化 ORM 框架集成、提高数据库操作效率方面发挥着至关重要的作用。通过本篇文章的介绍,相信你已经掌握了 Spring ORM 的基础概念和基本用法,并了解了如何在实际项目中使用它来管理数据库事务、优化数据访问层的架构。

在实际开发过程中,合理选择 ORM 框架、优化查询性能、避免常见问题(如 N+1 查询、事务失效等)至关重要。希望本篇文章能为你提供有价值的参考,让你在 Spring ORM 的应用和优化之路上更加顺畅!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/965754.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Ollama本地部署deepseek

1、下载安装Ollama 前往下载页面 https://ollama.com/download下载好安装包&#xff0c;如同安装软件一样&#xff0c;直接安装即可 win中默认为C盘&#xff0c;如果需要修改到其他盘&#xff0c;查找具体教程 运行list命令&#xff0c;检查是否安装成功 2、修改模型下载的…

约束布局属性学习

1、layout_constraintHorizontal_bias layout_constraintHorizontal_bias 是 ConstraintLayout 中的一个重要属性&#xff0c;用于控制一个视图在父视图或相关视图中水平位置的偏移。这种偏移通过在0到1之间的浮点值来设置&#xff0c;0代表完全靠近左边或起始位置&#xff0c…

Windows双网卡冲突导致网页加载过慢的解决方法 (修改跃点无效 远程桌面连接)

【本文发布于https://blog.csdn.net/Stack_/article/details/145494160&#xff0c;未经许可不得转载&#xff0c;转载须注明出处】 办公室内&#xff0c;我的笔记本和台式机都连接WIFI进行上网&#xff0c;网段是192.168.0.x&#xff0c;网关192.168.0.101 现在要通过Windows自…

轻量级服务器http-server

安装 sudo npm install http-server -g 运行 1. 直接去到要跑起来的目录&#xff0c;在终端输入 cd xxxx文件夹http-server //只输入http-server的话&#xff0c;更新了代码后&#xff0c;页面不会同步更新http-server -c-1 //同步更新页面http-server -a 127.0.0.1 -p 808…

代码随想录算法【Day38】

Day38 322. 零钱兑换 思路 完全背包 代码 class Solution { public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount 1, INT_MAX);dp[0] 0;for (int i 0; i < coins.size(); i) { // 遍历物品for (int j coins[i]; j <…

python+opencv+open3d实现鼠标手画多边形裁剪分割点云操作

👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… ​💫签名:面朝大海,春暖花开! python+opencv+open3d实现鼠标手画多边形裁剪分割点云操作 引言使用效果:代码pcd_roi_crop.py:引言 当我们想对一个不规则物体的图像或者点云裁剪时,直接手动输入…

STM32的HAL库开发---通用定时器(TIMER)---定时器脉冲计数

一、脉冲计数实验原理 1、 外部时钟模式1&#xff1a;核心为蓝色部分的时基单元&#xff0c;时基单元的时钟源可以来自四种&#xff0c;分别是内部时钟PCLK、外部时钟模式1&#xff0c;外部时钟模式2、内部定时器触发&#xff08;级联&#xff09;。而脉冲计数就是使用外部时钟…

Redis05 - 性能调优和缓存问题

Redis性能调优和缓存问题 文章目录 Redis性能调优和缓存问题一&#xff1a;链路追踪判断是不是redis出了问题二&#xff1a;redis变慢原因1&#xff1a;使用复杂度过高的命令(*)1.1&#xff1a;查看redis慢日志1.2&#xff1a;延迟变大原因分析1.3&#xff1a;解决方案 2&#…

漫步 C++ 之途,领略引用的独特风姿

在C中&#xff0c;引用&#xff08;Reference&#xff09;是一种非常有用的特性&#xff0c;它允许为一个变量创建一个别名&#xff08;Alias&#xff09;。引用在很多情况下可以替代指针&#xff0c;但使用起来更加方便和安全。以下是对C引用的详细介绍&#xff0c;包括其定义…

Spring Boot Web 入门

目录 Spring Boot Web 是 Spring Boot 框架的一个重要模块&#xff0c;它简化了基于 Spring 的 Web 应用程序的开发过程。以下是一个 Spring Boot Web 项目的入门指南&#xff0c;涵盖了项目创建、代码编写、运行等关键步骤。 1. 项目创建 使用 Spring Initializr 使用 IDE …

Java 多线程、线程同步、线程池

一. 线程 1. 线程&#xff1a;线程(Thread)是一个程序内部的一条执行流程。 2. 程序中如果只有一条执行流程&#xff0c;那这个程序就是单线程的程序。 二. 多线程 多线程是指从硬件上实现多条执行流程的技术(多条线程由CPU负责调度) Javas是通过java.lang.Thread类的对象来代…

20.[前端开发]Day20-王者荣耀项目实战(三)

01_(掌握)王者荣耀-main-赛事新闻列表实现 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" …

【Langchain学习笔记(一)】Langchain介绍

Langchain介绍 Langchain介绍前言1、Langchain 是什么2、为什么要用 Langchain3、Langchain 的核心4、Langchain 的底层原理5、Langchain 的应用场景 Langchain介绍 前言 想象一下&#xff0c;如果你能让聊天机器人不仅仅回答通用问题&#xff0c;还能从你自己的数据库或文件…

IDEA2024版本创建Sping项目无法选择Java 8

目录 一、背景二、解决方式&#xff08;替换创建项目的源地址&#xff09; 一、背景 IDEA2024创建一个springboot的项目&#xff0c;本地安装的是1.8&#xff0c;但是在使用Spring Initializr创建项目时&#xff0c;发现版本只有17、21、23。 二、解决方式&#xff08;替换创…

C++11(四)

目录 包装器 function包装器 bind绑定 更改实参传递的顺序和实参传递的个数 线程库 本期我们将继续进行C11新特性的学习。 包装器 function包装器 function包装器&#xff0c;我们也称之为适配器&#xff0c;本质上就是一个类模板&#xff0c;为什么要引入function包…

MySQL 数据库编程-C++

目录 1 数据库基本知识 1.1 MYSQL常见命令 1.2 SQL注入 1.3 ORM框架 1 数据库基本知识 MySQL 为关系型数据库(Relational Database Management System), 这种所谓的"关系型"可以理解为"表格"的概念, 一个关系型数据库由一个或数个表格组成&#xff1a…

【算法篇】贪心算法

目录 贪心算法 贪心算法实际应用 一&#xff0c;零钱找回问题 二&#xff0c;活动选择问题 三&#xff0c;分数背包问题 将数组和减半的最小操作次数 最大数 贪心算法 贪心算法&#xff0c;是一种在每一步选择中都采取当前状态下的最优策略&#xff0c;期望得到全局最优…

5 计算机网络

5 计算机网络 5.1 OSI/RM七层模型 5.2 TCP/IP协议簇 5.2.1:常见协议基础 一、 TCP是可靠的&#xff0c;效率低的&#xff1b; 1.HTTP协议端口默认80&#xff0c;HTTPSSL之后成为HTTPS协议默认端口443。 2.对于0~1023一般是默认的公共端口不需要注册&#xff0c;1024以后的则需…

动态规划LeetCode-1035.不相交的线

在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#xff0c;这些直线需要同时满足&#xff1a; nums1[i] nums2[j]且绘制的直线不与任何其他连线&#xff08;非水平线&#xff09;相…

禅道社区版项目管理软件部署(记录篇)

系统要求&#xff08;这里推荐使用docker容器化方式&#xff09;安装前的准备Docker快速安装最后通过查看地址验证是否部署成功开始界面化安装配置 禅道&#xff08;ZenTao&#xff09;是一款国产开源的项目管理软件&#xff0c;专注于敏捷开发流程&#xff0c;支持 Scrum 和 K…