从零开始搭建企业管理系统(三):集成 Spring Data Jpa

集成 Spring Data Jpa

    • 什么是 Jpa
    • 什么是 Spring Data Jpa
    • 什么是 Hibernate
    • JPA、Spring Data Jpa、Hibernate 之间的关系
    • 集成 Spring Data Jpa
      • POM 依赖
      • 配置文件
      • UserEntity
      • 启动程序
      • Jpa 配置
      • Jpa 注解
      • UserRepository
      • UserService
      • UserServiceImpl
      • UserController
      • BaseEntity

什么是 Jpa

JPA(Java Persistence API)是 Java 标准中的一套 ORM 规范(提供了一些编程的 API 接口,具体实现由 ORM 厂商实现,如Hiernate、TopLink 、Eclipselink等都是 JPA 的具体实现),借助 JPA 技术可以通过注解或者 XML 描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中(即Object Model与Data Model间的映射)。

什么是 Spring Data Jpa

Spring Data JPA 是在实现了 JPA 规范的基础上封装的一套 JPA 应用框架(Criteria API还是有些复杂)。虽然 ORM 框架都实现了 JPA 规范,但是在不同的 ORM 框架之间切换仍然需要编写不同的代码,而使用 Spring Data JPA 能够方便的在不同的 ORM 框架之间进行切换而不需要更改代码。Spring Data JPA 旨在通过统一 ORM 框架的访问持久层的操作,来提高开发人的效率。

Spring Data JPA 是一个 JPA 数据访问抽象。也就是说 Spring Data JPA 不是一个实现或 JPA 提供的程序,它只是一个抽象层,主要用于减少为各种持久层存储实现数据访问层所需的样板代码量。但是它还是需要 JPA 提供实现程序,其实 Spring Data JPA 底层就是使用的 Hibernate 实现。

什么是 Hibernate

Hibernate对数据库结构提供了较为完整的封装,Hibernate的O/R Mapping实现了POJO 和数据库表之间的映射,以及SQL 的自动生成和执行。往往只需定义好了POJO 到数据库表的映射关系,即可通过Hibernate 提供的方法完成持久层操作。甚至不需要对SQL 的熟练掌握, Hibernate/OJB 会根据制定的存储逻辑,自动生成对应的SQL 并调用JDBC 接口加以执行。

hibernate对 JPA 的支持,不是另提供了一套专用于 JPA 的注解。一些重要的注解如@Column, @OneToMany等,hibernate并没有提供,这说明 JPA 的注解已经是hibernate 的核心,hibernate只提供了一些补充,而不是两套注解。JPA 和hibernate都提供了的注解(例如@Entity),若 JPA 的注解够用,就直接用,若 JPA 的注解不够用,直接使用hibernate的即可。

JPA、Spring Data Jpa、Hibernate 之间的关系

533121-20160122105513781-959577889.png

集成 Spring Data Jpa

POM 依赖

<!--删掉 jdbc 依赖-->
<!--<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>-->

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

配置文件

spring:
  jpa:
    # 控制台显示SQL
    show-sql: true
    hibernate:
      # 程序启动后自动更新或者创建数据表结构
      ddl-auto: update
    properties:
      hibernate:
        # 格式化打印 sql
        format_sql: true

UserEntity

@Data
@Entity
@Table(name = "sys_user")
public class UserEntity {

    /**
     * Id 表示为表 ID
     * GenerationType.IDENTITY 使用自增长主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String nickname;

    private Integer age;

    private String email;

    private String password;
    
    private String createUser;
    
    private String updateUser;
    
    private Date createTime;
    
    private Date updateTime;
}

启动程序

做完这些操作之后我们先启动程序看看情况,先给大家看看我的数据库下现在是没有任何一张表的。

在这里插入图片描述

ok,启动程序,查看一下结果,程序启动成功,但是我先日志里面打印了一段 SQL 语句。
在这里插入图片描述

很明显是一个建表语句,并且字段名和类型跟我们刚才新建的 UserEitity 一模一样,猜测是 Jpa 自动根据实体类帮我们建表了,我们查看一下数据库,果然多了一张 sys_user 表。

在这里插入图片描述

这是因为我们刚才配置了 spring.jpa.hibernate.ddl-auto=update,update 默认会根据添加了@Entity的映射实体类进行表结构的创建或更新,生产上我们应该关闭这个功能,配置为 none。

spring.jpa.hibernate.ddl-auto 配置比较重要,表示建表的策略,可选的枚举值如下:

  • create:不管表是否存在,每次启动都会重新建表(会导致数据丢失)。
  • create-drop:启动的时候创建表,程序退出(SessionFactory 关闭)的时候删除表。
  • none:不进行任何操作。
  • update:如果数据表不存在则创建,在实体对象被修改后,下次启动重新修改表结构(不会删除已经存在的数据)。
  • validate:启动的时候验证数据表的结构。

Jpa 配置

Spring Data JPA已经提供了一些独立于供应商的配置选项(例如SQL日志),Spring Boot将这些选项以及一些针对Hibernate的选项作为外部配置属性公开。

属性描述备注
spring.jpa.database要操作的目标数据库,默认自动检测可选配置
spring.jpa.database-platform要操作的目标数据库的名称,默认情况下是自动检测的可以使用"Database"枚举
spring.jpa.defer-datasource-initializationdatasource初始化延迟默认false
spring.jpa.generate-ddl启动时是否初始化数据库schema默认false
spring.jpa.show-sql是否启用SQL语句日志记录默认false
spring.jpa.mapping-resources资源映射(等价于persistence.xml中的“mapping-file”条目)
spring.jpa.open-in-viewOpenEntityManagerInViewInterceptor注册,将JPA EntityManager绑定到线程,用于整个请求处理默认true
spring.jpa.properties要在JPA提供程序上设置的其他本地属性例如:spring.jpa.properties.hibernate.connection.autocommit
spring.data.jpa.repositories.enabled是否启用JPA Repository默认true
spring.data.jpa.repositories.bootstrap-modeJPA Repository的引导模式三种模式:DEFAULT(默认), DEFERRED ,LAZY
spring.jpa.hibernate.ddl-autoDDL模式hibernate.hbm2ddl的快捷方式,当使用嵌入式数据库时,默认为create-drop,否则默认值为 none
spring.jpa.hibernate.naming.implicit-strategy全限定名的隐式命名策略例如:org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
spring.jpa.hibernate.naming.physical-strategy物理命名策略的完全限定名
spring.jpa.hibernate.use-new-id-generator-mappings是否使用Hibernate更新的IdentifierGenerator AUTO, TABLE和SEQUENCE。默认true。hibernate.id.new_generator_mappings快捷方式

Jpa 注解

看完了 Spring Boot 中对于 Jpa 的配置,我们再大致的了解一下 Jpa 提供的一些注解,后续我们需要经常用到这些注解来进行开发。

注解解释
@Entity声明类为实体或表。
@Table声明表名。
@Basic指定非约束明确的各个字段。
@Embedded指定类或它的值是一个可嵌入的类的实例的实体的属性。
@ld指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Transient指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@Column指定持久属性栏属性。
@SequenceGenerator指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列.
@TableGenerator指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
@AccessType这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并目不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@JoinColumn指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@UniqueConstraint指定的字段和用于主要或辅助表的唯一约束。
@ColumnResult参考使用select-子句的SQL查询中的列名。
@ManyToMany定义了连接表之间的多对多对多的关系。
@ManyToOne定义了连接表之间的多对一的关系。
@OneToMany定义了连接表之间存在一个一对多的关系。
@OneToOne定义了连接表之间有一个一对一的关系。
@NamedQueries指定命名查询的列表。
@NamedQuery指定使用静态名称的查询。

UserRepository

要创建一个 repository 接口,你首先需要定义一个实体类专用的 repository 接口。该接口必须继承 Repository,并将其泛型设置为实体类和ID类型。

# 表示这是一个 Repository 接口
@Repository
public interface UserRepository extends JpaRepository<UserEntity, Long>, Serializable {
}

定义好了 UserRepository接口之后,我们就可以对 sys_user 表进行增删改查了,我们编写一个测试类来测试一下。

@Slf4j
@SpringBootTest
class ApplicationTests {

    @Resource
    UserRepository userRepository;

    @Test
    void saveUserTest() {
        UserEntity user = new UserEntity();
        user.setName("张三");
        user.setNickname("法外狂徒");
        user.setAge(18);
        user.setPassword("666");
        // 保存用户并返回
        UserEntity result = userRepository.save(user);
        log.info("用户添加成功:{}", result);
    }

    @Test
    void contextLoads() {
    }

}

运行程序后,程序执行成功,查看日志发现执行了一条插入语句,数据库中也是正常的存在一条数据,说明Spring Data Jpa 已经集成成功,是不是很简单,只需要定义一个 Entity 和一个 Repository,什么增删改查的方法都不用定义就可以了。那么这是为什么呢,咱们继续往下看。

在这里插入图片描述

其实就是我们集成的 JpaRepository接口中已经预定义了各种 CRUD 方法,我们只需要在集成的时候插入相应的泛型对象就可以。 JpaRepository 的泛型对象是一个实体类型和 ID 类型,他继承的接口是 ListCrudRepositoryListPagingAndSortingRepository以及 QueryByExampleExecutor 接口。

在这里插入图片描述

继续点进去 ListCrudRepository 发现继承的是 CrudRepository,他两其实是提供了同等的方法,但ListCrudRepository 返回 List,而 CrudRepository 的方法返回 Iterable

ListPagingAndSortingRepository是可以进行分页和排序操作的接口。

在这里插入图片描述

最后点进去CrudRepository发现继承的是Repository接口,他是Spring Data repository 抽象的中心接口,它把要管理的 domain 类以及 domain 类的ID类型作为泛型参数。这个接口主要是作为一个标记接口,用来捕捉工作中的类型,并帮助你发现扩展这个接口的接口。 CrudRepositoryListCrudRepository 接口为被管理的实体类提供复杂的CRUD功能。

在这里插入图片描述

repository 接口的继承关系

在这里插入图片描述

CrudRepository 接口提供的一些方法

public interface CrudRepository<T, ID> extends Repository<T, ID> {

  <S extends T> S save(S entity);      1

  Optional<T> findById(ID primaryKey); 2

  Iterable<T> findAll();               3

  long count();                        4

  void delete(T entity);               5

  boolean existsById(ID primaryKey);   6

  // … more functionality omitted.
}

1、保存给定的实体。
2、根据ID返回实体。
3、返回所有实体。
4、返回实体数量。
5、删除给定的实体。
6、根据ID判断实体是否存在。

ok,我们接着完善一下代码,编写完整的业务逻辑吧。

UserService

public interface UserService {

    /**
     * 根据ID查询用户
     *
     * @param id 用户ID
     * @return UserEntity 用户信息
     */
    UserEntity get(Long id);

    /**
     * 查询全部用户
     *
     * @return List<UserEntity> 用户集合
     */
    List<UserEntity> lists();

    /**
     * 保存用户
     *
     * @param user 用户信息
     */
    void save(UserEntity user);

    /**
     * 修改用户
     *
     * @param user 用户信息
     */
    void update(UserEntity user);

    /**
     * 删除用户
     *
     * @param id 用户id
     */
    void delete(Long id);

    /**
     * 分页查询用户
     *
     * @param pageable 分页参数
     * @return Page<UserEntity> 分页用户
     */
    Page<UserEntity> page(Pageable pageable);

}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserRepository userRepository;

    @Override
    public UserEntity get(Long id) {
        return userRepository.getReferenceById(id);
    }

    @Override
    public List<UserEntity> lists() {
        return userRepository.findAll();
    }

    @Override
    public void save(UserEntity user) {
        userRepository.save(user);
    }

    @Override
    public void update(UserEntity user) {
        userRepository.save(user);
    }

    @Override
    public void delete(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public Page<UserEntity> page(Pageable pageable) {
        return userRepository.findAll(pageable);
    }
}

UserController

@RestController
@RequestMapping("/sys/user")
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping("/{id}")
    public UserEntity get(@PathVariable Long id) {
        return userService.get(id);
    }

    @GetMapping("/list")
    public List<UserEntity> lists() {
        return userService.lists();
    }

    @GetMapping("/page")
    public Page<UserEntity> page(int page, int size) {
        return userService.page(PageRequest.of(page - 1, size));
    }

    @PostMapping
    public void save(@RequestBody UserEntity user) {
        userService.save(user);
    }

    @PutMapping
    public void update(@RequestBody UserEntity user) {
        userService.update(user);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}

ok,启动程序,使用 postman 进行测试一下,下一节我们集成 Swagger,就可以不用 postman 测试接口了。

在这里插入图片描述

证明接口是OK滴,这些方法都是一些基础的方法,复杂的用法我们后面遇到了再说。

BaseEntity

我们编写这个 BaseEntity 的目的就是,将所有的 Entity 中共有的属性给他抽取出来,像是createUser、createTIme、updateUser以及updateTime 这些字段,同时进行一个数据的自动填充,我们在插入数据的时候就不需要关注这几个字段的值了。

1、添加@EnableJpaAuditing注解,启用jpa的审计功能

@EnableJpaAuditing
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

2、在基础类上添加jpa实体侦听器@EntityListeners(AuditingEntityListener.class),并且在具体属性上添加@CreatedBy、@CreatedDate、@LastModifiedBy、@LastModifiedBy注解。

@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {

    @CreatedBy
    @Column(name = "create_user", updatable = false)
    private String createUser;

    @LastModifiedBy
    @Column(name = "update_user")
    private String updateUser;

    @CreatedDate
    @Column(name = "create_time", updatable = false)
    private Date createTime;

    @LastModifiedDate
    @Column(name = "update_time")
    private Date updateTime;
}

3、配置jpa自动填充用户,因为jpa是不知道当前的操作用户是谁的

@Configuration
public class JpaAuditorConfig implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        // TODO 先写死,等集成了Spring Security后再获取实际用户
        return Optional.of("admin");
    }
}

4、修改 UserEntity 集成 BaseEntity

@Data
@Entity
@Table(name = "sys_user")
public class UserEntity extends BaseEntity implements Serializable {

    /**
     * Id 表示为表 ID
     * GenerationType.IDENTITY 使用自增长主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String nickname;

    private Integer age;

    private String email;

    private String password;
}

5、启动测试

在这里插入图片描述
在这里插入图片描述

插入成功我们,看一下数据,没得任何问题,数据填充成功,不过这个时间格式还得再调整调整。再配置文件里面添加 Jackson 的配置就行了。

spring:
  jackson:
    # 全局日期格式化
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

本节内容到这里就结束啦。

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

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

相关文章

YOLOv8-Seg改进:ASF-YOLO助力小目标分割| 2023年12月最新成果

🚀🚀🚀本文改进: ASF-YOLO一种新的特征融合网络架构,该网络由两个主要的组件网络组成,可以为小目标分割提供互补的信息:(1)SSFF模块,它结合了来自多尺度图像的全局或高级语义信息;(2)TFE模块,它可以捕获小目标的局部精细细节等 🚀🚀🚀YOLOv8-seg创新专栏:ht…

什么是接口测试?如何做接口测试

接口测试是指对系统或应用程序接口进行测试&#xff0c;以验证接口的功能、可靠性、性能、安全性等方面的需求是否被满足。接口测试可以用于测试不同系统、模块、组件之间的交互和通信&#xff0c;包括 Web 接口、网络接口、数据库接口等。其重点是测试数据传输、数据格式、数据…

CTF竞赛二进制类题型解析(逆向工程、二进制漏洞利用、缓冲区溢出)

在CTF&#xff08;Capture The Flag&#xff09;竞赛中&#xff0c;二进制&#xff08;Binary&#xff09;类题型通常涉及逆向工程、二进制漏洞利用、缓冲区溢出等方面的挑战。这些题目考验参赛者对底层编程和系统安全的理解。以下是15道二进制类题目及其标准答案&#xff0c;并…

【深度学习】PHP操作mysql数据库总结

一.PHP数据库的扩展分类 1.MySQL 扩展是针对 MySQL 4.1.3 或更早版本设计的&#xff0c;是 PHP 与 MySQL数据库交互的早期扩展。由于其不支持 MySQL 数据库服务器的新特性&#xff0c;且安全性差&#xff0c;在项目开发中不建议使用&#xff0c;可用 MySQLi 扩展代替。 2.MySQ…

python:五种算法(PSO、RFO、HHO、WOA、GWO)求解23个测试函数(python代码)

一、五种算法简介 1、粒子群优化算法PSO 2、红狐优化算法RFO 3、哈里斯鹰优化算法HHO 4、鲸鱼优化算法WOA 5、灰狼优化算法GWO 二、5种算法求解23个函数 &#xff08;1&#xff09;23个函数简介 参考文献&#xff1a; [1] Yao X, Liu Y, Lin G M. Evolutionary program…

设计模式再探——装饰模式

目录 一、背景介绍二、思路&方案三、过程1.装饰模式简介2.装饰模式的类图3.装饰模式代码4.装饰模式&#xff0c;职责父类拆分的奥义5.装饰模式&#xff0c;部件抽象类的无中生有 四、总结五、升华 一、背景介绍 最近公司在做架构模型的时候&#xff0c;涉及到装饰模式的研…

ChatGLM3:打造更智能、更安全的代码解释器和工具使用体验

ChatGLM3 是由智谱AI训练的第三代大型语言模型&#xff0c;它不仅能理解和生成人类语言&#xff0c;还能执行代码、调用工具&#xff0c;并以 markdown 格式进行响应。为了提高用户体验&#xff0c;同时避免用户输入的注入攻击&#xff0c;ChatGLM3 采用了全新的对话格式。下载…

Qt::UniqueConnection和lambda一块用无效

如果槽函数是lambda。 那么用了Qt::UniqueConnection也会出现槽函数被多次调用的问题。 原因&#xff1a; 参考官方文档&#xff1a; QObject Class | Qt Core 5.15.16https://doc.qt.io/qt-5/qobject.html#connect

小航助学2023年9月电子学会Scratch二级真题(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09; 单选题2.00分 删除编辑附件图文 答案:D 第1题点击绿旗&#xff0c;运行程序后&#xff0c;舞台上的图形是&#xff1f;&#xff08; &#xff09; A、画笔粗细…

【JMeter】使用nmon进行性能资源监控

一、前言 ​ 在工作中可能会遇到需要在压测的时候对Linux服务器进行性能资源监控的情况。这时可以用nmon来对服务器进行监控。 二、nmon的下载安装 1.查看系统信息 shell cat /etc/os-release结果为 shell PRETTY_NAME"Debian GNU/Linux 12 (bookworm)" NAME&qu…

Linux shell编程学习笔记35:seq

0 前言 在使用 for 循环语句时&#xff0c;我们经常使用到序列。比如&#xff1a; for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i * 2 $(expr $i \* 2)"; done 其中的 1 2 3 4 5 6 7 8 9 10;就是一个整数序列 。 为了方便我们使用数字序列&#xff0c;Linux提供了…

AdobeXD 是什么?你想知道的都在这里!

AdobeXD 是一个功能强大的原型创建工具。使用这个工具&#xff0c;你可以更快地开发你的设计。让你的项目有条不紊&#xff0c;消除拖延工作流程的重复任务和单调任务。快速与开发团队分享详细的设计规范。使用 AdobeXD 能够把创意迅速转化为原型&#xff0c;创建、构建、共享原…

vivado约束方法2

排序约束条件 因为XDC约束是按顺序应用的&#xff0c;并且是基于明确的优先级排列的规则&#xff0c;您必须仔细检查约束的顺序。 Vivado IDE为您的设计提供了全面的可视性。要逐步验证约束&#xff0c;请执行以下操作&#xff1a; 1.运行相应的报告命令。 2.查看Tcl控制台…

I/O设备模型

I/O设备模型 绝大部分的嵌入式系统都包括一些I/O&#xff08;Input/Outut&#xff0c;输入/输出&#xff09;设备&#xff0c;例如仪器上的数据显示屏、工业设备上的串口通信、数据采集设备上用于保存数据的Flash或SD卡&#xff0c;以及网络设备的以太网接口等。 I/O设备模型…

计网Lesson10 - 网络层之IP协议分析

文章目录 网络层协议IPv4 数据报格式IPv4 数据报首部格式版本&#xff08;Version&#xff09;首部长度&#xff08;Header Length&#xff09;区分服务&#xff08;Differentiated Services Field&#xff09;可选字段填充总长度&#xff08;Total Length&#xff09;标识、标…

算法Day32 买卖椰子水

买卖椰子水 Description 在海滩上&#xff0c;一杯椰子水的售价为5元。一名顾客一次购买一杯椰子水&#xff08;按照bills支付的顺序&#xff09;。 每位顾客购买椰子水时&#xff0c;可能向你支付 5 元、10 元或 20 元。你必须给每个顾客正确找零&#xff0c;对于支付 5 元的…

CentOS7 OpenSSL升级到OpenSSH9.5p1

原文链接&#xff1a; CentOS7 OpenSSL升级1.1.1w&#xff1b;OpenSSH 升级 9.5p1 保姆级教程 openssl从3.1.0升级到3.1.1遇到的问题 注意操作时需要联网请参考如下链接 内网服务器联网安装依赖参见我的另一篇文章 一、 前言 OpenSSH 的加密功能需要用到OpenSSL&#xff0c;所…

在服务器上配置jupyter notebook便于本地访问

文章目录 需求配置1. 安装jupyter2. 生成配置文件3. 设置登录密码并生成秘钥a. 打开服务器的终端b. 设置密码 4. 修改配置文件a. 进入配置文件所在的文件夹b. 编辑配置文件jupyter_notebook_config.pyc. 保存文件 5. 在服务器上生成jupyter访问地址 关注公众号&#xff1a;『 …

别整那么复杂,一二三就行了!Windows下vscode运行c++代码

这里写自定义目录标题 别整那么复杂&#xff0c;三步就行&#xff01;Windows下vscode运行c代码下载VScode&#xff1a;https://code.visualstudio.com/Download#安装四个插件下载mingw-64&#xff1a;https://sourceforge.net/projects/mingw-w64/files/mingw-w64/大功告成&am…

ubuntu 自动安装 MKL Intel fortran 编译器 ifort 及完美平替

首先据不完全观察&#xff0c;gfortran 与 openblas是 intel fortran 编译器 ifotr和mkl的非常优秀的平替&#xff0c;openblas连函数名都跟mkl一样&#xff0c;加了一个下划线。 1&#xff0c; 概况 https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-too…