【spring】Spring Data --Spring Data JPA

news2024/11/26 18:28:28

Spring Data 的委托是为数据访问提供熟悉且符合 Spring 的编程模型,同时仍保留着相关数据存储的特​​殊特征。

它使使用数据访问技术、关系和非关系数据库、map-reduce 框架和基于云的数据服务变得容易。这是一个伞形项目,其中包含许多特定于给定数据库的子项目。这些项目是通过与这些令人兴奋的技术背后的许多公司和开发商合作开发的。

Spring Data特征

  • 强大的存储库自状语从句:定义对象映射抽象艺术
  • 从存储库方法名称派生的动态查询
  • 提供基本属性的实现域基类
  • 支持透明审计(创建、最后更改)
  • 可以集成自定义存储库代码
  • 通过 JavaConfig 和自定义 XML 特有的一个简单集成 Spring
  • 与 Spring MVC 控制器的高级集成
  • 跨店持久化实验支持

Spring Data主要模块

  • Spring Data Commons - 支撑每个Spring Data模块的核心Spring概念。
  • Spring Data JDBC - 对 JDBC 的 Spring Data 存储库支持。
  • Spring Data JDBC Ext - 支持标准 JDBC 的数据库特定扩展,包括支持 Oracle RAC 快速连接故障转移、AQ JMS 支持和使用高级数据类型的支持。
  • Spring Data JPA - 对 JPA 的 Spring Data 存储库支持。
  • Spring Data KeyValue -Map基于存储库和SPI,可构建用于键值存储的Spring Data模块。
  • Spring Data LDAP - Spring Data 存储的支持Spring Data LDAP。
  • Spring Data MongoDB - 基于 Spring 的对象文档支持和 MongoDB 存储库。
  • Spring Data Redis - 从 Spring 应用程序轻松配置和访问 Redis。
  • Spring Data REST - 将 Spring Data 存储库导出为超媒体驱动的 RESTful 资源。
  • Spring Data for Apache Cassandra - 轻松配置和访问Apache Cassandra或规模、高可用性、程序数据的Spring。
  • Spring Data for Apache Geode - 轻松配置和访问Apache Geode,以实现高度一致性、低延迟、深度数据的Spring应用程序。
  • Spring Data for Pivotal GemFire - 为您的高度一致性、低延迟/高吞吐量、数据的 Spring 应用程序简单配置和访问 Pivotal GemFire。

Spring Data社区模块

  • Spring Data Aerospike - Aerospike 的 Spring Data 模块。

  • Spring Data ArangoDB - ArangoDB 的 Spring Data 模块。

  • Spring Data Couchbase - Couchbase 的 Spring Data 模块。

  • Spring Data Azure Cosmos DB - Microsoft Azure Cosmos DB 的 Spring Data 模块。

  • Spring Data Cloud Datastore - Google Datastore 的 Spring Data 模块。

  • Spring Data Cloud Spanner - Google Spanner 的 Spring Data 模块。

  • Spring Data DynamoDB - DynamoDB 的 Spring Data 模块。

  • Spring Data Elasticsearch - 用于 Elasticsearch 的 Spring Data 模块。

  • Spring Data Hazelcast - 为 Hazelcast 提供 Spring Data 存储库支持。

  • Spring Data Jest - 基于 Jest REST 客户端的 Elasticsearch 的 Spring Data 模块。

  • Spring Data Neo4j - Neo4j 的基于 Spring 的对象图支持和存储库。

  • 适用于 Spring Data 的 Oracle NoSQL 数据库 SDK - 适用于 Oracle NoSQL 数据库和 Oracle NoSQL 云服务的 Spring Data 模块。

  • Spring Data for Apache Solr - 为深入搜索的 Spring 应用程序轻松配置和访问 Apache Solr。

  • Spring Data Vault - 在 Spring Data KeyValue 以外的 Vault 存储库中建立。

Spring Data相关模块

  • Spring Data JDBC Extensions - 为Spring Framework中提供的JDBC支持提供扩展。

  • Spring for Apache Hadoop——通过提供统一的配置模型和使用的API来简化Apache Hadoop,以使用HDFS、MapReduce、Pig和Hive。

  • Spring 内容 - 将内容与您的 Spring 数据实体相关联,将其存储在许多不同的存储中,包括文件系统、S3、数据库或 Mongo 的 GridFS。

Spring Data 发布模块

Spring Data R2DBC - R2DBC的Spring Data支持。

Spring Data JPA

ORM

在解释什么是JPA和Spring Data JPA之前我们应该先来了解一下什么是ORM。ORM(Object-Relational Mapping, 对象关系映射),是一种面向对象编程语言中的对象和数据库中的数据之间的映射。使用ORM工具、框架可以让应用程序操作数据库。

在过去,有很多针对Java的ORM框架,但是每一套框架都有自己的一套操作方法和规范,这就使得Java程序操作不同数据库时显得杂乱无章。于是乎,Sun公司推出了一套操作持久层(数据库)的规范(API)用于结束这种乱象,这套规范也就是JPA。

JPA

JPA(Java Persistence API,Java持久层API) 是Sun公司定义的一套基于ORM的接口规范,用于给Java程序操作数据库。JPA 通过 JDK 5.0 注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 。在这之后很多ORM框架实现了JPA规范,其中最有名的有Hibernate、TopLink、JDO等。JPA 和 Hibernate 的关系就像 JDBC 和 JDBC 驱动的关系,JPA 是规范,Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现。

jpa_and_hibernate.png

JPA的优势

标准化

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同
样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在 不同的 JPA 框架下运行。

容器级特性的支持

JPA 框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的 局限,在企业应用发挥更大的作用。

简单方便

JPA 的主要目标之一就是提供更加简单的编程模型:在 JPA 框架下创建实体和创建 Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity 进行注释,JPA的 框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。 JPA 基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成

查询能力

JPA 的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是 Hibernate HQL 的等价物。JPA 定义了独特的 JPQL(Java Persistence Query Language),JPQL 是 EJB QL 的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而 不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询

高级特性

JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系。这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性。
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!
Spring Data JPA 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现,在实际的工作工程中,推荐使用 Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的 ORM 框架时提供了极大的方便,同时也使数据库层操作更加简单,方便。

Spring Data JPA

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!

Spring Data JPA 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现,在实际的 工作工程中,推荐使用 Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的 ORM 框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦。

III. 第一个Spring Data JPA项目

步骤如下

  1. 在pom.xml中导入依赖
org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-starter-web
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. 配置application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/jpa_study?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
  data:
    rest:
      basePath: /api
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

server:
  port: 8080
  1. 编写实体类
package com.soul.jpastudy.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@NoArgsConstructor
@AllArgsConstructor

/**
 * 客户的实体类
 *      配置映射关系
 *          1. 实体类和表的映射关系
 *          2. 实体类中属性和表中字段的映射关系
 *  @Entity:声明实体类
 *  @Table: 配置实体类和表的映射关系
 *      name: 配置数据库表的名称
 */

@Entity
@Table(name = "cst_customer")
public class Customer {

    @Id // 声明主键的配置
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
    @Column(name = "cust_id")   // 映射数据库表中的字段
    private Long custId;

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

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

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

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

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

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

}
  1. 编写Repository
package com.soul.jpastudy.repository;

import com.soul.jpastudy.domain.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RepositoryRestResource(collectionResourceRel = "customers", path = "customers")
public interface CustomerRepository extends JpaRepository<Customer, Long>{

    Customer findByCustName(String custName);

    @Query("select c from Customer c")
    List<Customer> findAll();

    @Transactional
    @Modifying
    @Query("update Customer c set c.custName = ?1 where c.custId = ?2")
    int updateCustomer(@Param("custName") String custName, @Param("custId") Long custId);

    @Transactional
    @Modifying
    @Query("delete from Customer c where c.custId = :custId and c.custIndustry = :custIndustry")
    int deleteCustomer(@Param("custId") Long custId, @Param("custIndustry") String custIndustry);

}
  1. 单元测试
@SpringBootTest
class JpaStudyApplicationTests {

    @Autowired
    private CustomerRepository customerRepository;

    @Test
    void testFindByCustName(){
        Customer customer = customerRepository.findByCustName("testName");
        System.out.println(customer);
    }

    @Test
    void testFindAll() {
        List<Customer> all = customerRepository.findAll();
        for (Customer customer : all) {
            System.out.println(customer);
        }
    }

    @Test
    void testUpdateCustomer() {
        int row = customerRepository.updateCustomer("testUpdate", 1L);
        System.out.println(row);
        testFindAll();
    }

    @Test
    void testDeleteCustomer() {
        int row = customerRepository.deleteCustomer(1L, "testIndustry");
        System.out.println(row);
        testFindAll();
    }

    @Test
    void testSaveCustomer() {
        Customer customer = new Customer();
        customer.setCustName("save test");
        customer.setCustLevel("save level");
//        customer.setCustId(1L);   // 加上是更新某某,不加是添加新的一行数据
        customerRepository.save(customer);
        testFindAll();
    }

IV. JPQL

基于首次在 EJB2.0 中引入的 EJB 查询语言(EJB QL),Java JPQL(Java Persistence Query Language)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将 SQL 语法和简单查询语义绑定在一起使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的 SQL。

其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。

基本语法

select 实体别名.属性名,
from 实体名 as 实体别名 
where 实体别名.实体属性 op 比较值

# example
update Customer c set c.custName = ?1 where c.custId = ?2 # ?后跟变量序号(详见第一个Spring Data JPA项目)
delete from Customer c where c.custId = :custId and c.custIndustry = :custIndustry # :后跟变量名(详见第一个Spring Data JPA项目)

动态查询

在Spring Data JPA中,可以使用匿名内部类的方式添加动态条件,实现动态查询。步骤如下:

  1. 通过匿名内部类的方式创建一个Specification对象
  2. 编写toPredicate方法(
  • root: Table对应的Entity
  • CriteriaBuilder用于创建条件
  1. 编写具体的条件

示例代码:

@Test
public void testDynamicQuery() {
    List<User> users = userRepository.findAll(new Specification<User>() {
        @Override
        public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
            Predicate predicate = null;

            Path<String> pwdPath = root.get("pwd");
            Predicate pwdPredicate = criteriaBuilder.equal(pwdPath, "123");
            predicate = criteriaBuilder.and(predicate, pwdPredicate);
            Path<String> namePath = root.get("name");
            Predicate namePredicate = criteriaBuilder.like(namePath, "%Jack%");
            predicate = criteriaBuilder.and(pwdPredicate, namePredicate);
            Path<Integer> idPath = root.get("id");
            Predicate idPredicate = criteriaBuilder.equal(idPath, 2);
            predicate = criteriaBuilder.and(predicate, idPredicate);
            return predicate;
        }
    });
    
    // print results
    for (User user : users) {
        System.out.println(user);
    }
}

一对多、多对一、多对多

Spring Data JPA中可以在实体类属性上添加@ManyToOne、@OneToMany、@ManyToMany注解配置多对一、一对多和多对多。

1. 一对多、多对一

@OneToMany:

作用:建立一对多的关系映射

属性:

  • targetEntityClass:指定多的多方的类的字节码
  • mappedBy:指定从表实体类中引用主表对象的名称。
  • cascade:指定要使用的级联操作
  • fetch:指定是否采用延迟加载
  • orphanRemoval:是否使用孤儿删除

@ManyToOne

作用:建立多对一的关系
属性:

  • targetEntityClass:指定一的一方实体类字节码
  • cascade:指定要使用的级联操作
  • fetch:指定是否采用延迟加载
  • optional:关联是否可选。如果设置为 false,则必须始终存在非空关系。

@JoinColumn

作用:用于定义主键字段和外键字段的对应关系。
属性:

  • name:指定外键字段的名称
  • referencedColumnName:指定引用主表的主键字段名称
  • unique:是否唯一。默认值不唯一
  • nullable:是否允许为空。默认值允许。
  • insertable:是否允许插入。默认值允许。
  • updatable:是否允许更新。默认值允许。
  • columnDefinition:列的定义信息。

级联操作

级联操作:指操作一个对象同时操作它的关联对象

使用方法:只需要在操作主体的注解上配置 cascade

/**
    * cascade:配置级联操作 
    * CascadeType.MERGE 级联更新 
    * CascadeType.PERSIST 级联保存:
    * CascadeType.REFRESH 级联刷新:
    * CascadeType.REMOVE 级联删除: 
    * CascadeType.ALL 包含所有
*/ 
@OneToMany(mappedBy="customer",cascade=CascadeType.ALL)

示例代码

@Entity
@Table(name = "article")
@IdClass(ArticlePrimaryKey.class)
@DynamicUpdate
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Article implements Serializable {

    @ManyToOne(targetEntity = User.class)
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private User user;

    @Id
    @Column(name = "article_id", nullable = false)
    private Integer articleId;

    @Column(name = "article_name")
    private String articleName;
} 
@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

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

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

    @Column(name = "country_id")
    private int countryId;


    @OneToMany(targetEntity = Article.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private Set<Article> articles;
}

2. 多对多

@ManyToMany

作用:用于映射多对多关系
属性: cascade:配置级联操作。

  • fetch:配置是否采用延迟加载。
  • targetEntity:配置目标的实体类。映射多对多的时候不用写。

@JoinTable

作用:针对中间表的配置
属性:

  • name:配置中间表的名称
  • joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
  • inverseJoinColumn:中间表的外键字段关联对方表的主键字段

@JoinColumn

作用:用于定义主键字段和外键字段的对应关系。
属性:

  • name:指定外键字段的名称
  • referencedColumnName:指定引用主表的主键字段名称
  • unique:是否唯一。默认值不唯一
  • nullable:是否允许为空。默认值允许。
  • insertable:是否允许插入。默认值允许。
  • updatable:是否允许更新。默认值允许。
  • columnDefinition:列的定义信息。

多表+动态查询

步骤

1. 创建结果实体类

package com.soul.entity;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserArticleDTO {
    private Integer id;

    private String name;

    private String articleName;
}

2. 编写Repository

package com.soul.repository;

import com.soul.entity.Article;
import com.soul.entity.User;
import com.soul.entity.UserArticleDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

@Repository
public class UserArticleDao {
    @Autowired
    @PersistenceContext
    private EntityManager em;

    static final Integer PAGE_SIZE = 2;

    public List<UserArticleDTO> findUserArticle(int currentPage) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<UserArticleDTO> query = builder.createQuery(UserArticleDTO.class);

        // from table
        Root<User> rootUser = query.from(User.class);
        Root<Article> rootArticle = query.from(Article.class);

        // where conditions
        List<Predicate> predicates = new ArrayList<>();

        Predicate predicate1 = builder.equal(rootUser.get("id"), rootArticle.get("userId"));
        Predicate predicate2 = builder.equal(rootArticle.get("articleName"), "macbook");
        Predicate predicate3 = builder.like(rootArticle.get("articleName"), "%ms surface%");
        Predicate predicateOr = builder.or(predicate2, predicate3);
        predicates.add(predicate1);
        predicates.add(predicateOr);

        Predicate finalPredicate = builder.and(predicates.toArray(new Predicate[predicates.size()]));


        query.multiselect(rootUser.get("id").as(Integer.class), rootUser.get("name").as(String.class),
                rootArticle.get("articleName").as(String.class))
                .where(finalPredicate);

        // no paging
        // List<UserArticleDTO> resultList = em.createQuery(query).getResultList();
        // return resultList;

        // add paging to query
        TypedQuery<UserArticleDTO> typedQuery = em.createQuery(query);
        typedQuery.setFirstResult((currentPage - 1) * PAGE_SIZE);
        typedQuery.setMaxResults(PAGE_SIZE);

        // execute query
        List<UserArticleDTO> resultList = typedQuery.getResultList();

        return resultList;

    }
}

3. 测试

    @Test
    public void testUserArticleDao() {
        List<UserArticleDTO> userArticle = userArticleDao.findUserArticle(1);
        for (UserArticleDTO userArticleDTO : userArticle) {
            System.out.println(userArticleDTO);
        }
    }

Spring Data JPA 对比 MyBatis

比较

  • hibernate是面向对象的,而MyBatis是面向关系的

  • 数据分析型的OLAP应用适合用MyBatis,事务处理型OLTP应用适合用JPA

  • 项目维护迭代维度比较(长期快速迭代类、变动较小的类型)

追求快速迭代,需求快速变更,灵活的 mybatis 修改起来更加方便,而且一般每一次的改动不会带来性能上的下降。JPA经常因为添加关联关系或者开发者不了解优化导致项目越来越糟糕(这里可能要考研功力了)

比较总结

  • 表关联较多的项目,优先使用mybatis

  • 持续维护开发迭代较快的项目建议使用mybatis,因为一般这种项目需要变化很灵活,对sql的灵活修改要求较高

  • 对于传统项目或者关系模型较为清晰稳定的项目,建议JPA(比如DDD设计中的领域层)

  • 目前微服务比较火,基于其职责的独立性,如果模型清晰,可以考虑使用JPA,但如果数据量较大全字段返回数据量大的话可能在性能有影响,需要根据实际情况进行分析

总结

Spring Data JPA 是Spring Data中一款强大的用于操作关系型数据库的技术。它的出现,省去了我们编写Dao层的步骤。在业务逻辑相对简单的时候,使用它会极大的提高开发效率。但是当业务逻辑太过复杂时,Spring Data JPA缺乏灵活性的问题就会暴露出来,这个时候MyBatis反而是更好的选择。

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

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

相关文章

详述java的设计模式(二)

1.工厂模式 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;属于创建型模式&#xff0c;是指由一个工厂类根据传入的参数&#xff0c;动态决定应该创建哪一个产品类的对象&#xff0c;而被创建的对象通常都具有共同的父类或接口&#xff0c;这种模式又叫做静态工…

数据结构和算法学习

文章目录精通一个领域切题四件套算法算法的五个条件流程图数据结构数据与信息数据信息数据结构和算法数据结构算法时间复杂度空间复杂度数组 Array优点缺点数组和链表的区别时间复杂度链表 Linked List优点缺点时间复杂度单向链表双向链表循环链表双向循环链表堆栈 Stack队列 Q…

涂鸦开发资源中心硬核上线!支持产物包可视化、自由裁剪开发框架等功能

开发过程对于程序猿们来说&#xff0c;就像建碉堡&#xff0c;碉堡的建成速度、创造力&#xff0c;以及精致和牢固程度&#xff0c;取决于工具称不称手。不称手的开发工具&#xff0c;不仅能让人心力交瘁&#xff0c;还会多掉几根头发。 为了帮助开发者获得更好的开发体验&…

【搞透C语言指针】那年我双手插兜, 不知道指针是我的对手

☃️内容专栏&#xff1a;【C语言】进阶部分 ☃️本文概括&#xff1a; 征服C语言指针&#xff01;一篇文章搞清楚指针的全部要点。 ☃️本文作者&#xff1a;花香碟自来_ ☃️发布时间&#xff1a;2023.3.3 目录 一、字符指针 二、指针数组 三、数组指针 1.数组指针的定义…

UML常见图的总结

一、概述 UML&#xff1a;Unified Modeling Language&#xff0c;统一建模语言&#xff0c;支持从需求分析开始的软件开发的全过程。是一个支持模型化和软件系统开发的图形化语言、为软件开发的所有阶段提供模型化和可视化支持&#xff0c;包括由需求分析到规格&#xff0c;到…

ESP32设备驱动-SHT11温度湿度传感器驱动

SHT11温度湿度传感器驱动 SHT1x 数字湿度传感器是一种可回流焊接的传感器。 SHT1x 系列包括带有 SHT10 湿度传感器的低成本版本、带有 SHT11 湿度传感器的标准版本和带有 SHT15 湿度传感器的高端版本。 与 SHTxx 湿度传感器系列中的所有其他 Sensirion 传感器类型一样,它们经…

H2数据库连接时用户密码错误:Wrong user name or password [28000-214] 28000/28000 (Help)

H2数据库连接时用户密码错误: 2023-03-03 08:25:07 database: wrong user or password; user: "SA" org.h2.message.DbException: Wrong user name or password [28000-214]出现的问题配置信息原因解决办法org.h2.message.DbException: Wrong user name or password …

Python从入门到转行,看完这一篇就够了

Python零基础入门 零基础入门就得从最基本的变量&#xff0c;语法格式&#xff0c;数据类型&#xff0c;函数&#xff0c;作用域&#xff0c;模块等基本知识入手&#xff08;有编程基础基础也得这么来&#xff09; 和篮球一样&#xff0c;先来三步上篮&#xff1a; Python基…

Spring Boot 分片上传、断点续传、大文件上传、秒传

文件上传是一个老生常谈的话题了&#xff0c;在文件相对比较小的情况下&#xff0c;可以直接把文件转化为字节流上传到服务器&#xff0c;但在文件比较大的情况下&#xff0c;用普通的方式进行上传&#xff0c;这可不是一个好的办法&#xff0c;毕竟很少有人会忍受&#xff0c;…

MySQL面试题-基础篇

目录 前言 数据库基础 1.什么是关系型数据库和非关系型数据库&#xff1f; 2.什么是 SQL&#xff1f; 3.MySQL 有什么优点&#xff1f; 4.MySQL 的基础架构? 存储引擎 1.MySQL 支持哪些存储引擎&#xff1f;默认使用哪个&#xff1f; 2.MySQL 存储引擎架构了解吗&…

C# IoC控制反转学习笔记

一、什么是IOC IoC-Invertion of Control&#xff0c;即控制反转&#xff0c;是一种程序设计思想。 先初步了解几个概念&#xff1a; 依赖&#xff08;Dependency&#xff09;&#xff1a;就是有联系&#xff0c;表示一个类依赖于另一个类。 依赖倒置原则&#xff08;DIP&a…

苹果ipa软件下载网站和软件的汇总

随着时间的流逝&#xff0c;做苹果版软件安装包下载网站和软件的渐渐多了起来。 当然&#xff0c;已经关站、停运、下架、倒闭的苹果软件下载网站和软件我就不说了&#xff0c;也不必多说那些关站停运下架倒闭的网站和软件了。 下面我统计介绍的就是苹果软件安装包下载网站和软…

系列十二、MySQL管理

一、系统数据库 Mysql数据库安装完成后&#xff0c;自带了一下四个数据库&#xff0c;具体作用如下&#xff1a;二、常用工具 2.1、mysql 2.1.1、概述 该mysql不是指mysql服务&#xff0c;而是指mysql的客户端工具。 2.1.2、语法 # 语法 &#xff1a; mysql [options] [dat…

分库分表、分库分表带来的问题

文章目录1.分库垂直分库水平分库2.分表垂直分表水平分表3.水平分表的路由方式&#xff08;1&#xff09;范围路由&#xff08;2&#xff09;Hash 路由4.分库分表带来的问题分库&#xff08;1&#xff09;事务的问题注意&#xff08;2&#xff09;跨库 JOIN 问题分表&#xff08…

k8s-故障转移 livenessProbe readinessProbe 学习总结

k8s-故障转移学习总结 大纲 概念K8S中Pod健康检查livenessProbe & readinessProbelivenessProbe 存活探测实例readinessProbe 就绪探测实例 概念 故障转移有哪些情况 物理机故障程序故障 在计算机术语中&#xff0c;故障转移&#xff08;英语&#xff1a;failover&am…

深入底层源码的Listener内存马(内存马系列篇三)

写在前面 继前面的FilterServlet内存马技术&#xff0c;这是系列文章的第三篇了&#xff0c;这篇将给大家带来的是Listener内存马技术。 前置 什么是Listener&#xff1f; 监听器 Listener 是一个实现特定接口的 Java 程序&#xff0c;这个程序专门用于监听另一个 Java 对象…

Pag的2D渲染执行流程

Pag的渲染 背景 根据Pag文章里面说的&#xff0c;Pag之前长时间使用的Skia库作为底层渲染引擎。但由于Skia库体积过大&#xff0c;为了保证通用型&#xff08;比如兼容CPU渲染&#xff09;做了很多额外的事情。所以Pag的工程师们自己实现了一套2D图形框架替换掉Skia&#xff…

GC Garbage Collectors

本质一、算法1、哪些是垃圾&#xff1f;引用计数法&#xff1a;reference countPython中使用了。个对象如果没有任何与之关联的引用&#xff0c;即他们的引用计数都不为 0&#xff0c;则说明对象不太可能再被用到&#xff0c;那么这个对象就是可回收对象。漏洞&#xff1a;循环…

C/C++每日一练(20230303)

目录 1. 字符串相乘 2. 单词拆分 II 3. 串联所有单词的子串 1. 字符串相乘 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 示例 1: 输入: num1 "2", num2 "3"…

【Linux】PXE+Kickstart无人值守安装系统

文章目录前言一、简介二、配置DHCP三、TFTP四、SYSLinux服务程序五、vsftpd服务六、Kickstart应答文件七、自动安装系统八、总结前言 本文来记录下PXEKickstart无人值守安装系统。 当需要安装OS的主机数量较多时&#xff0c;我们不可能通过U盘或光盘给这一台台主机去安装操作系…