SpringData JPA - ORM 框架下,打造高效数据访问层

news2024/11/23 17:23:06

目录

一、SpringData JPA 概述

1.1、什么是 JPA 

1.2、什么是 ORM

1.3、什么是 Hibernate

1.4、JPA 和 Hibernate 的关系

1.5、JPA 的优势

二、SpringData JPA 实战开发

2.1、依赖

2.2、配置文件

2.3、启动类

2.4、创建实体

2.5、基于 JpaRepository 的 CRUD

三、SpringDataJPA 多种查询方式

3.1、JpaRepository 查询

3.2、方法命名规则查询

3.3、JPQL 查询

3.4、SQL 查询

3.5、JpaSpecificationExecutor 动态查询


一、SpringData JPA 概述


1.1、什么是 JPA 

全英文名叫 Java Persistence API,就是 java 持久化 api ,是SUN公司推出的一套基于 ORM 的规范。

1.2、什么是 ORM

ORM(Object Relational Mapping)表示对象关系映射. 简单来讲,通过 ORM,就可以把对象映射到关系型数据库中(为了不用 JDBC 那套方法来操作数据库).

1.3、什么是 Hibernate

Hibernate 是一个对象关系映射框架,对 JDBC 进行了非常轻量级的封装,将 对象 与 数据库 简历映射关系,一个全自动的 ORM 框架.  Hibernate 可以自动生成 SQL 语句,自动执行,使得 Java 程序员可以通过面向对象的思想来操纵数据库.

1.4、JPA 和 Hibernate 的关系

JPA 和 Hibernate 的关系就像 JDBC 和 JDBC驱动 的关系,JPA 是规范,Hibernate 除了作为 ORM 框架之外,也是一种 JPA 实现.

简单来讲,如果使用 JPA 规范数据库操作,底层需要 Hibernate 作为其实现完成持久化.

1.5、JPA 的优势

a)标准化:

JPA 是 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都需要遵循同样的框架,提供相同的 API,大大提高了可移植性性.

b)特性支持:

JPA 框架支持大数据集、事务、并发等容器级事务,在大型企业中发挥极大作用.

c)使用方便:

JPA 的主要目标之一就是提供更加简单的编程模型:在 JPA 框架下创建实体和创建 Java 类一样简单,没有任何限制和约束,只需要使用 javax.persistence.Entity 注解.  另外还提供很多基础 CRUD,避免重复造轮子

d)高级特性:

JPA 中支持面向对象的高级特性,例如 类之间的继承、多态...  使得开发者最大限度的使用面向对象的模型设计企业应用.

二、SpringData JPA 实战开发


2.1、依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.2、配置文件

server:
  port: 9000

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/jpa?characterEncoding=utf8&useSSL=false
    username: root
    password: DJSAKOFH0*)(shdf*s*&_(fsbpf*&s)_fg*@_&fg@{!p_#*t_@!bfugiwofhg
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    database: mysql
    show-sql: true # 显示 sql 语句(项目上线后记得关闭)
    hibernate:
      ddl-auto: update
    open-in-view: false # 一般来讲,建议关闭

ddl-auto 熟悉用于设置自动表,可以实现自动在数据库中为我们创建一个表,表的结构会根据我们定义的实体类决定,具体有 4 种值:

  • create:启动时删除数据库中表,然后创建,退出时不删除数据表.
  • create-drop:启动时删除数据库中表,然后创建,退出时删除数据表,并且如果不存在就报错.
  • update:如果启动时表格式不一致则更新表,原有数据保留
  • validate:项目启动时,表结构进行校验,不一致则报错.
  • none:不采取任何措施.

Ps:表可以是自动创建的,但是数据库必须我们手动创建.

2.3、启动类

@EnableJpaAuditing //用来开启 JPA 审计功能
@SpringBootApplication
class JpaApplication

fun main(args: Array<String>) {
    runApplication<JpaApplication>(*args)
}

 @EnableJpaAuditing: 用来开启 JPA 审计功能,比如在建表中经常会加入 版本号、创建时间、修改时间、创建者、修改者 这五个字段.  为了简化开发,可以将其交给 JPA 来自动填充.

2.4、创建实体

import com.fasterxml.jackson.annotation.JsonFormat
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedBy
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.util.*
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.EntityListeners
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.Table
import javax.persistence.Version

@Entity
@Table(name = "user_info")
@EntityListeners(AuditingEntityListener::class)
data class Userinfo(

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    val username: String,

    val age: Int,

    //注意,关于审计信息,都需要使用 var 类型

    @Version
    var version: Long? = null,

    @CreatedBy
    @Column(name = "c_by")
    var cBy: String? = null,

    @LastModifiedBy
    @Column(name = "u_by")
    var uBy: String? = null,

    @CreatedDate
    @field:JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Column(name = "c_time")
    var cTime: Date? = null,

    @LastModifiedDate
    @field:JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Column(name = "u_time")
    var uTime: Date? = null,

)
注解作用常用属性
@Data给实体类加get/set/toString/EqualsAndHashCode方法,是lombok的注解
@Entity指定当前类是实体类
@Table指定实体类和表之间的对应关系name:指定数据库表的名称
@EntityListeners在实体类增删改的时候监听,为创建人/创建时间等基础字段赋值value:指定监听类
@Id指定当前字段是主键
@SequenceGenerator指定数据库序列别名sequenceName:数据库序列名
name:取的别名
@GeneratedValue指定主键的生成方式strategy :指定主键生成策略(一般设置 为GenerationType.IDENTITY,表示自增长)
generator:选择主键别名
@Column指定实体类属性和数据库表之间的对应关系(如果成员变量名和表字段名对应一致,可以省略)name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
nserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的DDL
@CreatedBy自动插入创建人
@CreatedDate自动插入创建时间
@LastModifiedBy自动修改更新人
@LastModifiedDate自动修改更细时间
@Version自动更新版本号
@JsonFormat插入/修改/读取的时间转换成想要的格式pattern:展示格式
timezone:国际时间

解释: 

a)主键策略: 

  • SEQUENCE 策略适合拥有序列的数据库,比如 Oracle;
  • IDENTITY 策略适合拥有主键自增长的数据库,比如 MySQL;
  • TABLE 策略是通过一张序列表来维护主键插入的值的,所以适合所有数据库;
  • AUTO 策略是 JPA 自行判断使用上面三个中的哪一个作为主键生成策略;

开发人员应该自行判断使用的是何种数据库,而不是由 JPA 进行判断。

b)审计功能

  • @Version:版本号;进行 update 操作时启动乐观锁,@Version 修饰的字段值与数据库中字段值一致才能进行修改
  • @CreatedDate :创建时间;进行 insert 操作时,将当前时间插入到 @CreatedDate 修饰字段中;进行 update 操作时,会随实体类中的 @CreatedDate 修饰的字段值进行修改
  • @CreatedBy:创建人;进行 insert 操作时,将当前用户名插入到 @CreatedBy 修饰字段中;进行update操作时,会随实体类中的 @CreatedBy 修饰的字段值进行修改
  • @LastModifiedDate:最后一次修改时间;进行 update 操作时,将当前时间修改进@LastModifiedDate 修饰字段中;进行 insert 操作时,将当前时间插入到 @LastModifiedDate 修饰字段中
  • @LastModifiedBy :最后一次修改的修改人;进行 update 操作时,将当前修改人修改进@LastModifiedBy 修饰的字段中;进行 insert 操作时,将当前用户名插入到@LastModifiedBy修饰字段中

c)启动审计条件:

  • 启动类上有 @EnableJpaAuditing 注解.
  • 实体类上方加上监听注解 @EntityListeners(AuditingEntityListener::class)

完成上述两个注解后,@CreatedDate、@LastModifiedBy、@Version 就生效了,但是创建人、修改人不会生效,需要我们创建一个配置类,实现 AuditorAware<String> 接口,如下:

@Configuration
class UserAuditor: AuditorAware<String> {

    /**
     * @return 获取当前创建或修改的用户
     */
    override fun getCurrentAuditor(): Optional<String> {
        return Optional.of("我是审计者 cyk")   
    }

}

Ps:正式项目中一般会从 JWT 或者 Session 中获取当前操作该表的用户是谁.

2.5、基于 JpaRepository 的 CRUD

Spring Data JPA 操作数据库,只需要自定有接口,并继承 JpaRepository 接口,无需再接口中定义任何方法,也不需要为接口提供实现类,就能完成基本 CRUD.

a)接口:

import org.cyk.jpa.model.Userinfo
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface UserRepoJpa: JpaRepository<Userinfo, Long>

b)测试类:

import org.cyk.jpa.model.Userinfo
import org.cyk.jpa.repo.UserRepoJpa
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import javax.annotation.Resource

@SpringBootTest
class JpaApplicationTests {

    @Resource
    private lateinit var userRepoJpa: UserRepoJpa

    @Test
    fun test() {
        val obj = Userinfo(
            username = "cyk3",
            age = 21,
        )
        userRepoJpa.save(obj)
        val result = userRepoJpa.findAll()
        result.forEach(::println)
    }

}

执行结果:

Ps:创建人和更新人埋坑,最后会补充~ 

c)SpringDataJPA 的接口继承关系:

Repository  (标记接口、做标记、Repository接口的子接口的实现类对象可以自动被SpringIOC容器所识别,此接口的子接口中可以定义一些指定规范的方法)
    ||
CrudRepository  (定义了一些基本的CRUD方法)
    ||
PagingAndSortingRepository  (定义了排序和分页相关的查询方法)
    ||
JpaRepository    (重写了一些基本测CRUD方法)
    ||
ArticleDao    (自己定义的接口)

三、SpringDataJPA 多种查询方式


3.1、JpaRepository 查询

a)只需要创建一个接口,让他继承 JpaRepository<T, ID> 接口即可

  • T:实体类
  • ID:id 类型
import org.cyk.jpa.model.Userinfo
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface UserRepoJpa: JpaRepository<Userinfo, Long>

 此时,你就可以直接使用 JpaRepository<T, ID> 接口 提供的方法:

b)测试:

import org.cyk.jpa.model.Userinfo
import org.cyk.jpa.repo.UserRepoJpa
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import javax.annotation.Resource

@SpringBootTest
class JpaApplicationTests {

    @Resource
    private lateinit var userRepoJpa: UserRepoJpa

    @Test
    fun test() {
        val obj = Userinfo(
            username = "cyk3",
            age = 21,
        )
        userRepoJpa.save(obj)
        val result = userRepoJpa.findAll()
        result.forEach(::println)
    }

}

3.2、方法命名规则查询

a)创建一个接口,继承 JpaRepository 接口,此时你就可以自定义一些方法(方法名有要求),SpringDataJPA 就会再程序执行的时候根据方法名进行解析,自动生成对应的查询语句.

b)规范:

  1. 查询起始词:查询方法通常以 findreadgetquerycountexists 等词开头。

  2. 属性引用:在起始词之后,你可以引用实体类的属性名(首字母大写)。例如,如果有一个名为 firstName 的属性,你可以通过 findByFirstName 来查询它。

  3. 条件组合:对于多个条件,你可以使用 And 或 Or 连接。例如,findByFirstNameAndLastName 会查找同时匹配 firstName 和 lastName 的记录。

  4. 排序:你可以使用 OrderBy 关键字并指定属性名和排序方向(如 Asc 或 Desc)来排序结果。

  5. 限制结果:使用 FirstTop 或 Limit 可以限制返回的记录数。例如,findFirstByName 会返回按 name 排序后的第一个结果。

  6. 聚合函数:Spring Data JPA 也支持聚合函数,如 countBysumByavgBy 等。

  7. 处理特殊情况:如果属性名包含特殊字符或与 SQL 关键字冲突,可以使用 @Column 注解来明确指定字段名。对于复杂的查询,可以使用 @Query 注解来编写自定义的 SQL 或 JPQL 查询。

  8. 命名规范:属性名在方法名中通常是大写的,以符合 Java 的命名规范,即使它们在数据库或实体类中是小写的。

  9. 分页:如果需要分页查询,可以在方法参数中添加 Pageable 类型的参数。

  10. 流和迭代:除了返回列表或单个实体,方法还可以返回流(Stream)或迭代器(Iterable),以支持更高效的内存使用。

例如:

import org.cyk.jpa.model.Userinfo
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface UserRepoName: JpaRepository<Userinfo, Long> {

    //直接查询
    fun findByUsername(username: String): List<Userinfo>

    //模糊查询
    fun findByUsernameLike(username: String): List<Userinfo>

    //and 查询
    fun findByUsernameAndAge(username: String, age: Int): List<Userinfo>

    //小于等于查询
    fun findByIdLessThanEqual(id: Long): List<Userinfo>

    //between 查询
    fun findByIdBetween(start: Long, end: Long): List<Userinfo>

    //in 查询
    fun findByIdIn(ids: List<Long>): List<Userinfo>

}

测试:

import org.cyk.jpa.repo.UserRepoName
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import javax.annotation.Resource

@SpringBootTest
class JpaNameApplicationTests {

    @Resource
    private lateinit var userRepoName: UserRepoName

    @Test
    fun test1() {
        userRepoName.findByUsername("cyk").forEach(::println)
    }

    @Test
    fun test2() {
        userRepoName.findByUsernameLike("%y%").forEach(::println)
    }

    @Test
    fun test3() {
        userRepoName.findByUsernameAndAge("cyk", 21).forEach(::println)
    }

    @Test
    fun test4() {
        userRepoName.findByIdLessThanEqual(2).forEach(::println)
    }

    @Test
    fun test5() {
        userRepoName.findByIdBetween(1, 3).forEach(::println)
    }

    @Test
    fun test6() {
        userRepoName.findByIdIn(listOf(1,2)).forEach(::println)
    }

}

3.3、JPQL 查询

JPQL,全称是 Java 持久化查询语言,是 JPA 中定义的一种查询语言. 此种语言的用意是让开发者忽略数据库表和表中的字段,而关注实体类及实体类中的属性。

写法十分类似于SQL语句的写法,但是要把查询的表名换成实体类的名称,把表中的字段名换成实体类的属性名称。

接口:

import org.cyk.jpa.model.Userinfo
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository

@Repository
interface UserRepoJpql: JpaRepository<Userinfo, Long> {

    //占位符从 1 开始
    @Query("from Userinfo where username = ?1 and age <= ?2")
    fun findByCond1(username: String, age: Int): List<Userinfo>

    //参数名 ":" 绑定
    @Query("from Userinfo where username = :username and age <= :age")
    fun findByCond2(@Param("username") username: String,
                    @Param("age") age: Int): List<Userinfo>

    //模糊查询 + 排序
    @Query("from Userinfo where username like %:username% order by cTime desc")
    fun findByCond3(@Param("username") username: String): List<Userinfo>

    //模糊查询 + 分页
    @Query("from Userinfo where username like %:username%")
    fun findByCond4(pageable: Pageable, @Param("username") username: String): List<Userinfo>

    //in 查询
    @Query("from Userinfo where age in :ages")
    fun findByCond5(@Param("ages") ages: List<Int>): List<Userinfo>

    //通过对象进行查询(SPEL 表达式查询)
    @Query("from Userinfo where username = :#{#userinfo.username} and age <= :#{#userinfo.age}")
    fun findByCond6(@Param("userinfo") userinfo: Userinfo): List<Userinfo>

}

测试:

import org.cyk.jpa.model.Userinfo
import org.cyk.jpa.repo.UserRepoJpql
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.domain.PageRequest
import javax.annotation.Resource

@SpringBootTest
class JpaJpqlApplicationTests {

    @Resource
    private lateinit var userRepoJpql: UserRepoJpql

    @Test
    fun test1() {
        userRepoJpql.findByCond1("cyk", 21).forEach(::println)
    }

    @Test
    fun test2() {
        userRepoJpql.findByCond2("cyk", 21).forEach(::println)
    }

    @Test
    fun test3() {
        userRepoJpql.findByCond3("y").forEach(::println)
    }

    @Test
    fun test4() {
        val pg = PageRequest.of(1, 2)
        userRepoJpql.findByCond4(pg, "y").forEach(::println)
    }

    @Test
    fun test5() {
        userRepoJpql.findByCond5(listOf(21,22,23)).forEach(::println)
    }

    @Test
    fun test6() {
        userRepoJpql.findByCond6(
            Userinfo(
                username = "cyk",
                age = 21
            )
        ).forEach(::println)
    }

}

3.4、SQL 查询

在 @Query 注解中,设置属性 nativeQuery = true,表示使用 SQL 语句进行查询.

基本不会使用这种情况,除非是非常复杂的业务情况.

接口:

import org.cyk.jpa.model.Userinfo
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query

interface UserRepoSql: JpaRepository<Userinfo, Long> {

    @Query(value = "select * from user_info where username = ?1 and age = ?2", nativeQuery = true)
    fun findByCond(username: String, age: Int): List<Userinfo>

}

测试:

import org.cyk.jpa.repo.UserRepoSql
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import javax.annotation.Resource

@SpringBootTest
class JpaSqlApplicationTests {

    @Resource
    private lateinit var userRepoSql: UserRepoSql

    @Test
    fun test() {
        userRepoSql.findByCond("cyk", 21).forEach(::println)
    }

}

3.5、JpaSpecificationExecutor 动态查询

类似我们写动态 SQL,给定的条件不是固定的,需要动态的构建查询语句.

SpringDataJPA 中,我们只需要自定义个接口,继承 JpaRepository 和 JpaSpecificationExecutor 接口即可.

接口:

import org.cyk.jpa.model.Userinfo
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.JpaSpecificationExecutor
import org.springframework.stereotype.Repository

@Repository
interface UserRepoJpaSpe: JpaRepository<Userinfo, Long>, JpaSpecificationExecutor<Userinfo>

测试:

import org.cyk.jpa.model.Userinfo
import org.cyk.jpa.repo.UserRepoJpaSpe
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.jpa.domain.Specification
import javax.annotation.Resource
import javax.persistence.criteria.Predicate

@SpringBootTest
class JpaSpeApplicationTests {

    @Resource
    private lateinit var userRepoJpaSpe: UserRepoJpaSpe

    //username 和 age 不为空才作为查询条件
    @Test
    fun test1() {
        //模拟外部输入
        val username: String? = ""
        val age: Int? = 21

        /**
         * 拼接查询条件
         * root: 代表实体对象,可以通过它获取属性值
         * cq: 用于生成SQL语句
         * cb: 用于拼接查询条件
         */
        val s = Specification<Userinfo> { root, cq, cb ->
            val predicates = mutableListOf<Predicate>()

            if (!username.isNullOrBlank()) {
                val p = cb.equal(root.get<String>("username"), username)
                predicates.add(p)
            }

            age?.let {
                val p = cb.equal(root.get<Int>("age"), it)
                predicates.add(p)
            }

            cb.and(*predicates.toTypedArray())
        }

        //查询
        userRepoJpaSpe.findAll(s).forEach(::println)
    }

    //查询 + 分页 + 排序(倒序)
    @Test
    fun test2() {
        //模拟外部输入
        val username: String? = ""
        val age: Int? = 21

        /**
         * 拼接查询条件
         * root: 代表实体对象,可以通过它获取属性值
         * cq: 用于生成SQL语句
         * cb: 用于拼接查询条件
         */
        val s = Specification<Userinfo> { root, cq, cb ->
            val predicates = mutableListOf<Predicate>()

            if (!username.isNullOrBlank()) {
                val p = cb.equal(root.get<String>("username"), username)
                predicates.add(p)
            }

            age?.let {
                val p = cb.equal(root.get<Int>("age"), it)
                predicates.add(p)
            }

            cb.and(*predicates.toTypedArray())
        }

        //分页 + 排序
        val pg = PageRequest.of(0, 3, Sort.by(Sort.Order.desc("cTime"))) //注意这里对应的是成员变量名(而非表中的字段名)

        val result = userRepoJpaSpe.findAll(s, pg)
        result.forEach(::println)
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

空闲缓冲区(empty) 和 非空缓冲区(full) 的的概念和区别【操作系统 生产者——消费者进程】

首先&#xff0c;我们得有个环境——通常是个缓冲池&#xff0c;这个池子里可以塞很多缓冲区&#xff0c;它们是用来存放数据的。生产者就是那个不停造东西的家伙&#xff0c;而消费者则是等着用这些东西的人。 1. 空闲缓冲区&#xff08;empty&#xff09;&#xff1a; 这玩意…

基于SSM的“大学生创新团队管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SSM的“大学生创新团队管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 首页页面 团队风采页面 团队招新页面…

《HCIP-openEuler实验指导手册》1.6 Apache静态资源配置(目录访问)

知识点 常用用途&#xff1a; 软件仓库镜像及提供下载服务&#xff1a; 配置步骤 删除网站主目录中的文件&#xff08;本实验机目录为/home/source ip为192.168.12.137 端口为81&#xff09; cd /home/source rm -rf *在主目录中新建6个文件夹如下图 mkdir test{1..6}新建…

Log4Qt日志框架 - 日志输出重定向(03)

Log4Qt日志框架 - 日志格式化&#xff08;02&#xff09;https://mp.csdn.net/mp_blog/creation/editor/138417616?spm1011.2266.3001.6217 一、Log4Qt输出重定向 Log4Qt继承关系图 AppenderSkeleton&#xff1a;实现一般的功能DebugAppender&#xff1a;将日志附加到平台调…

第Y9周:重要模块解读

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 目录 以con.py为例&#xff1a; 一、autopad 二、Conv 三、Focus 四、C2f 文件…

C++入门系列-基于范围的for循环(C++11)和指针空值nullptr(C++11)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 基于范围的for循环 范围for的语法 在C98中如果要遍历一个数组&#xff0c;可以按照以下方式进行&#xff1a; void TestFor() {int array[] { 1,2,3,4,5 };for (int i 1; i …

nuxt3使用记录六:禁用莫名其妙的Tailwind CSS(html文件大大减小)

发现这个问题是因为&#xff0c;今天我突然很好奇&#xff0c;我发现之前构建的自动产生的200.html和404.html足足290k&#xff0c;怎么这么大呢&#xff1f;不是很占用我带宽&#xff1f; 一个啥东西都没有的静态页面&#xff0c;凭啥这么大&#xff01;所以我就想着手动把他…

JavaEE 初阶篇-深入了解 Junit 单元测试框架和 Java 中的反射机制(使用反射做一个简易版框架)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Junit 单元测试框架概述 1.1 使用 Junit 框架进行测试业务代码 1.2 Junit 单元测试框架的常用注解&#xff08;Junit 4.xxx 版本&#xff09; 2.0 反射概述 2.1 获…

20240502解决ARM32编译器编译quectel-CM时for循环出错的解决

20240502解决ARM32编译器编译quectel-CM时for循环出错的解决 2024/5/2 17:17 缘起&#xff1a;QMIThread.c:2100:9: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode 1、修改Makefile为ARM32架构&#xff1a; Z:\quectel-CM\Makefile ifneq ($…

VFS 虚拟文件系统(上)

目录 概念 通用文件模型 VFS所处理的系统调用 VFS的数据结构 超级块对象 索引节点对象&#xff08;inode&#xff09; 文件对象 目录项对象 目录项高速缓存 与进程相关的文件 文件系统类型 特殊文件系统 文件系统类型注册 文件系统处理 命名空间 概念 虚拟文件系…

LabVIEW换智能仿真三相电能表研制

LabVIEW换智能仿真三相电能表研制 在当前电力工业飞速发展的背景下&#xff0c;确保电能计量的准确性与公正性变得尤为重要。本文提出了一种基于LabVIEW和单片机技术&#xff0c;具有灵活状态切换功能的智能仿真三相电能表&#xff0c;旨在通过技术创新提高电能计量人员的培训…

微信服装分销配送商城小程序的效果是什么

无论服装经销商还是厂家主要思考的就是怎样获客转化销售&#xff0c;衣服款式多样化、线下门店和线上电商平台各品牌竞争愈加激烈&#xff0c;客户消费渠道广&#xff0c;促进着商家需要寻找更多机会以及怎样服务好流量。 私域运营模式中小程序是重要的工具之一&#xff0c;服…

excel办公系列-图表元素及其作用

Excel图表元素及其作用 Excel图表由各种元素组成&#xff0c;每个元素都有其特定的作用&#xff0c;可以帮助我们更清晰地传达数据信息。下面将介绍Excel图表中常见的一些元素及其作用&#xff0c;并附上相关截图。 原始数据 月份 网站访问量 (万次&#xff09; 销售额 (万…

机器学习:深入解析SVM的核心概念【二、对偶问题】

对偶问题 **问题一&#xff1a;什么叫做凸二次优化问题&#xff1f;而且为什么符合凸二次优化问题&#xff1f;**为什么约束条件也是凸的半空间&#xff08;Half-Space&#xff09;凸集&#xff08;Convex Set&#xff09;半空间是凸集的例子SVM 约束定义的半空间总结 **问题二…

PDF中伪代码、原理示意图等导出为矢量图

需求&#xff1a;将 LaTeX 中生成的伪代码 PDF 转换成 svg 或 emf 格式的矢量图&#xff0c;然后插入 word 或 ppt 中。 1 伪代码PDF导出为矢量图 1.1 通过 Adobe Illustrator 处理将 先新建一个空白的PDF&#xff0c;然后文件-->置入导入PDF&#xff1b; 2.选中这个图片…

基于Springboot的交流互动系统

基于SpringbootVue的交流互动系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 帖子信息 聚会信息 后台登录 后台管理首页 用户管理 帖子分类管理 帖子信息…

C语言例题29:在屏幕上显示一个等腰三角形

#include <stdio.h>void main() {int i, j;int x;printf("输入等腰三角形行数&#xff1a;");scanf("%d", &x);for (i 1; i < x; i) {for (j i; j < x; j) {printf(" "); //输出空格占位}for (j 1; j < 2 * i; j) {printf…

HTTP协议Request

文章目录 HTTP协议介绍概念版本分类特点 浏览器抓包观察请求报文协议步骤实现 Request和Response概述Request对象Request继承体系Request获取请求数据获取请求行数据获取请求头数据获取请求体数据获取请求参数(通用方式) 解决post请求乱码问题解决思路解决方案 Request请求转发…

【20-时间序列预测:使用Scikit-learn处理时间数据】

文章目录 前言理解时间序列数据处理时间数据数据格式与解析时间组件提取时间序列可视化构建时间序列预测模型数据集分割特征工程选择模型验证与评估评价指标选择结论前言 时间序列预测在金融、天气预报和销售分析等领域中扮演着重要角色。在本文中,我们将探讨如何使用Scikit-l…

Linux快速安装Nginx和重新添加模块

目录 一、Nginx快速安装1、下载Nginx2、配置Nginx模块 二、Ngnix重新编译和安装模块 一、Nginx快速安装 1、下载Nginx 直接进入Nginx官网下载Linux最新稳定版本&#xff0c;我之前下载的版本是1.23.0。 2、配置Nginx模块 下载完后我把源码压缩文件解压放在/opt/appl/nginx…