Spring Boot第八章-Spring Data JPA

Spring Boot第八章-Spring Data JPA

前言:

  最近比较忙,拖了好久才开始写springboot相关的博客,springboot实战那本书已经练习完毕,感觉挺有意思的,从第八章开始才是后端最关心的部分,经常用到。

  好了,言归正传,本章关于spring data jpa的介绍挺多的,但是还是不够详细,在实际应用中我们还要处理好表与表之间的关系,各种相关注解,比如一对多的关系@OneToMany,@ManyToOne等等。还有懒加载的问题,比如在一对多中我在A表类中写了个子表类B的列表,采用懒加载的方式,不让每次查A的时候也查出所有的B,只有在需要B的时候才触发对B的查询。这个如果处理不好很容易出问题,比如数据库连接已经失效了,那么就不能再自动去查了,或者json解析的时候,这个临时类就会报错。

  废话了一大堆,这个以后再遇到可以单独讲讲,正片开始:

1.什么是spring data jpa

以下是作者的原话,介绍的挺不错。

在介绍Spring Data JPA的时候,我们首先认识下Hibernate。Hibernate是数据访问解决技术的绝对霸主,使用O/R映射(Object-Relational Mapping) 技术实现数据访问,O/R映射即将领域模型类和数据库的表进行映射,通过程序操作对象而实现表数据操作的能力,让数据访问操作无需关注数据库相关的技术。

随着Hibernate的盛行,Hibernate主导了EGB3.0的JPA规范,JPA即Java Persistence API。JPA是一个基于O/R映射的标准规范。所谓规范只定义标准规则(如注解,接口),不提供实现,而使用者只需要按照规范中定义的方式来使用,而不用和软件提供商的实现打交道。JPA的主要实现由Hibernate、EclipseLink和OpenJPA等,这也意味着我们只要使用JPA来开发,无论哪一个开发方式都是一样的。

  Spring Data JPA是Spring Data的一个子项目,关于Spring Data可以看springboot官网,有很多子项目,只不过目前遇到的业务还没用得到。

 2.定义数据访问层

  只需要定义一个类继承JpaRepository的接口,就可以使用默认的数据访问操作方法。

3.配置使用Spring Data JPA

  在Spring环境中,可以通过@EnableJpaRepositories注解开启Spring Data JPA的支持,@EnableJpaRepositories接收的value参数用来扫描数据库访问层所在包下的数据访问的接口定义。

4.定义查询方法

(1)根据属性名查询

根据属性名和关键字来查询

Spring Boot第八章-Spring Data JPA

 

(2)限制结果数量

通过top和first关键字来实现,例如:

findFirst10ByName

findTop10ByName

(3)使用JPA的NamedQuery

一个名称映射一个查询语句,在领域模型上面定义@NameQuery,在数据库操作接口里使用

(4)@Query

这也是比较常见的查询了,用这个注解在接口的方法上实现查询,在sql语句里查询参数上可以用参数索引,从1开始,比如?1,?2

也可以使用命名参数:比如:address

@Modifying和@Query注解组合来事件更新查询

(5)Specification

JPA提供了基于准则查询的方式,即Criteria查询。Spring Data JPA提供了一个Specification接口让我们更方便的构造准则查询,Specification接口定义了一个toPredicate方法用来构造查询条件。

(6)排序与分页

Spring Data JPA提供了Sort类,page接口和Pageable接口,可以方便的排序和分页

(7)自定义Repository

我们可以将自己常用的数据库操作封装起来,自定义Repository,具体看实战代码

4.springboot的支持

spring-boot-starter-data-jpa依赖于spring-boot-starter-jdbc,而spring boot对JDBC做了一些自动配置。

spring boot默认JPA的实现者是Hibernate

Spring Boot自动开启了对Spring Data JPA的支持,我们无需在配置类里显式声明@EnableJpaRepositories

5.实战:

(1)为了省时间,并没有按照作者所说安装oracle,使用的依旧是mysql。首先新建spring boot项目,依赖选择spring-boot-starter-data-jpa和spring-boot-starter-data-web。本实例基于spring boot2.0

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>LATEST</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>

(2)配置信息

   在application.properties配置数据库相关东西,注意mysql的配置,高版本一定要配置useSSL=false,还有时区

spring.jpa.database=mysql
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver  mysql connect jar包高版本用这个
#我后来改成5.1.42版本改成原始的配置了,mysql-connector-java如下所示:
#<dependency>
#<groupId>mysql</groupId>
#<artifactId>mysql-connector-java</artifactId>
#<version>5.1.42</version>
#</dependency>

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
#hibernate 根据实体类维护数据表结构的功能
#create:启动时删除上一次生成的表,并根据实体类生成表,表中数据会被清空
#create-drop:启动时根据实体类生成表,sessionFactory关闭时表会被删除
#update:启动时会根据实体类生成表,当实体类属性改变的时候,表结构也会更新,在初期开发阶段使用此项
#validate:启动时校验实体类和数据表是否一致,当我们数据结构稳定时采用此选项
#none:不采取任何措施
spring.jpa.hibernate.ddl-auto=update
#在控制台显示真实的sql语句
spring.jpa.show-sql=true
#让控制器输出的json字符串更美观
spring.jackson.serialization.indent-output=true

  数据表:

 

/*
Navicat MySQL Data Transfer

Source Server         : local
Source Server Version : 50716
Source Host           : localhost:3306
Source Database       : test

Target Server Type    : MYSQL
Target Server Version : 50716
File Encoding         : 65001

Date: 2018-08-05 18:10:03
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `person`
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
  `id` bigint(20) NOT NULL,
  `address` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of person
-- ----------------------------
INSERT INTO `person` VALUES ('1', '徐州', '14', '二狗');
INSERT INTO `person` VALUES ('2', '北京', '21', '哈德');
INSERT INTO `person` VALUES ('3', '北京', '12', '三国杀');
INSERT INTO `person` VALUES ('4', '上海', '23', '大噶湖人');
INSERT INTO `person` VALUES ('5', '南京', '42', '国家统一');
INSERT INTO `person` VALUES ('6', '北京', '21', '家人');

(3)定义映射实体类

package com.just.springjpa.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
//这里普通属性没有写@Column(属性映射字段名),会自动根据属性名生成字段名
@Entity
@NamedQuery(name="Person.withNameAndAddressNamedQuery",query = "select p from Person p where p.name=?1 and p.address=?2")
public class Person {
    @Id               //指定主键
    @GeneratedValue   //主键生成方式为自增
    private Long id;
    private String name;
    private Integer age;
    private String address;
    public Person(){
        super();
    }
    public Person(Long id, String name, Integer age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

(4)定义数据访问接口

 

package com.just.springjpa.dao;

import com.just.springjpa.domain.Person;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface PersonRepository extends JpaRepository<Person,Long> {
    //使用方法名查询,返回列表
    List<Person> findByAddress(String address);
    //使用方法名查询,返回单个对象
    Person findByNameAndAddress(String name,String address);
    //使用query查询,参数按照名称绑定
    @Query(value = "select p from Person p where p.name=:name and p.address=:address")
    Person withNameAndAddressQuery(@Param("name")String name,@Param("address")String address);
    //使用NamedQuery查询,在实体类中做了定义
    List<Person> withNameAndAddressNamedQuery(String name,String address);
}

(5)控制器以及部分测试结果

package com.just.springjpa.web;

import com.just.springjpa.dao.PersonRepository;
import com.just.springjpa.dao.PersonRepository2;
import com.just.springjpa.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class DataController {
    //Spring data jpa已经自动注册bean,可以直接自动注入
    @Autowired
    PersonRepository personRepository;

    /**
     * jpa自带的方法,可以直接保存
     * 保存单个,多个,根据id查找,id列表查找,查找所有,判断是否存在,计算总数,根据id删除,删除对象,删除一堆对象,删除所有等等,
     * 自带很多实现,不需要我们单独写了
     *     <S extends T> S save(S var1);
     *
     *     <S extends T> Iterable<S> saveAll(Iterable<S> var1);
     *
     *     Optional<T> findById(ID var1);
     *
     *     boolean existsById(ID var1);
     *
     *     Iterable<T> findAll();
     *
     *     Iterable<T> findAllById(Iterable<ID> var1);
     *
     *     long count();
     *
     *     void deleteById(ID var1);
     *
     *     void delete(T var1);
     *
     *     void deleteAll(Iterable<? extends T> var1);
     *
     *     void deleteAll();
     *
     */
    @RequestMapping("/save")
    public Person save(String name,String address,Integer age){
       Person person=new Person(null,name,age,address);
       return personRepository.save(person);
    }
    @RequestMapping("/q1")
    public List<Person> findByAddress(String address){
       List<Person> people=personRepository.findByAddress(address);
       return people;
    }
    @RequestMapping("/q2")
    public Person findByNameAndAddress(String name,String address){
        Person person=personRepository.findByNameAndAddress(name,address);
        return person;
    }
    @RequestMapping("/q3")
    public Person withNameAndAddressQuery(String name,String address){
        Person person=personRepository.withNameAndAddressQuery(name,address);
        return person;
    }
    @RequestMapping("/q4")
    public List<Person> withNameAndAddressNamedQuery(String name,String address){
        List<Person> people=personRepository.withNameAndAddressNamedQuery(name,address);
        return people;
    }
    //测试排序
    @RequestMapping("/sort")
    public List<Person> sort(){
        List<Person> people=personRepository.findAll(new Sort(Sort.Direction.ASC,"age"));
        return people;
    }
    //测试分页,分页参数里面也可以加排序
    @RequestMapping("/page")
    public Page<Person> page(Pageable pageable){
        Page<Person> personPage=personRepository.findAll(pageable);
        return personPage;
    }
}

部分测试结果展示:

Spring Boot第八章-Spring Data JPA

Spring Boot第八章-Spring Data JPA

Spring Boot第八章-Spring Data JPA

(6)自定义Repository实现

自定义Repository实现的目标:定制一个自动模糊查询,对于任意实体对象进行查询,对象里有几个值就查几个值,当值为字符类型时就自动like查询,其余类型自动等于查询

a.定义Specification

package com.just.springjpa.specs;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.collect.Iterables.toArray;

/**
 * 定制一个自动模糊查询,对于任意的实体对象进行查询,
 * 有几个值就查几个值,值为字符串类型就执行模糊查询
 * 本次demo重要的知识点:
 * jpa提供了基于准则查询的方式,即Criteria查询。而Spring Data Jpa提供了一个Specification(规范)接口让我们
 * 更方便的构造准则查询,Specification接口定义了一个toPredicate方法来构造查询条件
 * 其中,ROOT来获得需要查询的属性,criteriaBuilder来构造查询条件
 */
public class CustomerSpecs {
    /**
     * 定义一个返回值对象为Specification的方法(Specification:规格)
     * @param entityManager
     * @param example
     * @param <T>
     * @return
     */
    public static <T> Specification<T> byAuto(final EntityManager entityManager,T example){
        //获取当前实体类对象的类型
        final Class<T> type=(Class<T>) example.getClass();
        return new Specification<T>() {
            @Override
            public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //新建Predicate列表存储构造的查询条件
                List<Predicate> predicates=new ArrayList<>();
                //获得实体类的EntityType,从EntityType可以获得实体类的属性
                EntityType<T> entityType=entityManager.getMetamodel().entity(type);
                //对实体类的所有属性做循环
                for(Attribute<T,?> attr:entityType.getDeclaredAttributes()){
                    //获得实体类某个对象的值
                    Object attrValue=getValue(example,attr);
                    if(attrValue!=null){
                        //当前属性为字符类型的时候,用模糊查询
                       if(attr.getJavaType()==String.class){
                           if(!StringUtils.isEmpty(attrValue)){
                               //构造当前属性like属性值查询
                               predicates.add(criteriaBuilder.like(root.get(attribute(entityType,attr.getName(),String.class)),
                                       pattern((String)attrValue)));
                           }
                       }else{
                           //其余情况按照构造属性和属性值equal查询
                           predicates.add(criteriaBuilder.equal(root.get(attribute(entityType,attr.getName(),String.class)),
                                   attrValue));
                       }
                    }
                }
                return predicates.isEmpty()?criteriaBuilder.conjunction()
                        :criteriaBuilder.and(toArray(predicates,Predicate.class)); //将条件列表转换成predicate
            }

            //通过反射获得实体类对象对应的属性值
            private <T> Object getValue(T example,Attribute<T,?> attr){
                return ReflectionUtils.getField((Field) attr.getJavaMember(),example);
            }

            //获得实体类的当前属性的SingularAttribute,SingularAttribute包含的是实体类的某个单独属性
            private <E,T>SingularAttribute<T,E> attribute(EntityType<T> entity,String fieldName,Class<E> fieldClass){
                return entity.getDeclaredSingularAttribute(fieldName,fieldClass);
            }
        };
    }

    /**
     * 构造like的查询模式,前后都加%
     * @param str
     * @return
     */
    private static String pattern(String str){
        return "%"+str+"%";
    }


}

b.定义接口

package com.just.springjpa.support;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;

/**
 * 定义接口
 * @param <T>
 * @param <ID>
 */
@NoRepositoryBean
public interface CustomRepository<T,ID extends Serializable> extends JpaRepository<T,ID>,JpaSpecificationExecutor<T> {

    Page<T> findByAuto(T example, Pageable pageable);
}

c.定义实现

package com.just.springjpa.support;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import java.io.Serializable;

import static com.just.springjpa.specs.CustomerSpecs.*;

public class CustomRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements CustomRepository<T,ID> {
    private final EntityManager entityManager;

    public CustomRepositoryImpl(Class<T> domainClass,EntityManager entityManager){
         super(domainClass,entityManager);
         this.entityManager=entityManager;
    }
    @Override
    public Page<T> findByAuto(T example, Pageable pageable) {
        return findAll(byAuto(entityManager,example),pageable);
    }
}

d.定义repositoryFactoryBean

package com.just.springjpa.support;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

/**
 * 自定义CustomRepositoryFactoryBean替代默认的RepositoryFactoryBean,我们会获得一个RepositoryFactory,
 * RepositoryFactory将会注册我们自定义的Repository的实现
 * @param <T>
 * @param <S>
 * @param <ID>
 */
public class CustomRepositoryFactoryBean<T extends JpaRepository<S,ID>,S,ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new CustomRepositoryFactory(entityManager);
    }

    public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
        super(repositoryInterface);
    }

    private static class CustomRepositoryFactory extends JpaRepositoryFactory{

        public CustomRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
        }

        @Override
        protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {
            return new CustomRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
        }

        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return CustomRepositoryImpl.class;
        }
    }
}

e.使用

package com.just.springjpa.dao;

import com.just.springjpa.domain.Person;
import com.just.springjpa.support.CustomRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface PersonRepository2 extends CustomRepository<Person,Long> {
    //使用方法名查询,返回列表
    List<Person> findByAddress(String address);
    //使用方法名查询,返回单个对象
    Person findByNameAndAddress(String name,String address);
    //使用query查询,参数按照名称绑定
    @Query(value = "select p from Person p where p.name=:name and p.address=:address")
    Person withNameAndAddressQuery(@Param("name")String name, @Param("address")String address);
    //使用NamedQuery查询,在实体类中做了定义
    List<Person> withNameAndAddressNamedQuery(String name,String address);
}

f.配置

package com.just.springjpa;

import com.just.springjpa.support.CustomRepositoryFactoryBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class SpringjpaApplication {

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

g.controller里测试

 @GetMapping("/auto")
    public Page<Person> auto(Person person,Pageable pageable){
        Page<Person> people=personRepository2.findByAuto(person,pageable);
        return people;
    }

自定义Repository实现测试结果:

Spring Boot第八章-Spring Data JPA

简单的就到这里啦,以后项目中遇到相关的问题再单独写一个博客聊聊。

最后推荐一波springboot官网关于Spring Data JPA的说明,很好的参考文档

官网参考:

https://spring.io/projects/spring-data-jpa

使用:

https://docs.spring.io/spring-data/jpa/docs/2.0.9.RELEASE/reference/html/

Spring Boot第八章-Spring Data JPA

项目码云地址

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100284.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 微信公众平台-微信服务号开发

    文章目录背景:一、微信各个平台介绍二、公众平台介绍三、开发前准备四、服务器配置五、服务器验证六、消息接收七、客服消息八、获取素材九、相关工具十、最终效果展示总结背景:近期接到了涉及微信开放平台和微信公众平台相关的开发需求,开发过程中踩了许多坑,把相关问题整理记录下来以便巩固记忆,并把总结的经验分享出来,本篇分享微信服务号开发,希望可以给大家提供帮助一、微信各个平台介绍1、微信开放平台:面向开发人员,为网站、App提供微信第三方登录功能,为App提供支付功能。2、微信公众平台:对应的是公众号,包括订

  • TCP四次挥手和TIME_WAIT

    TCP四次挥手和TIME_WAITFIN_WAIT_1:FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情…

  • 如何把pyc反编译成py_exe文件反编译源码工具

    如何把pyc反编译成py_exe文件反编译源码工具将pyc文件反编译成python源代码

  • 使用matlab绘制分段函数的三种方法

    使用matlab绘制分段函数的三种方法找到了三种绘制分段函数的方法,绘制如下函数第一种方法:%第一种分段函数t1=0:0.1:10;v1=t1;t2=10:0.1:20;v2=0*t2+10;t3=20:0.1:30;v3=30-t3;t=[t1t2t3];v=[v1v2v3];plot(t,v);axis([032012]);第二种方法:%第二种分段函数表示方法t=0:0.01:30;v=zeros(size(t));fori=1:length(t)ift(i…

  • 每天进步一点点——五分钟理解一致性哈希算法(consistent hashing)[通俗易懂]

    每天进步一点点——五分钟理解一致性哈希算法(consistent hashing)[通俗易懂]五分钟让你深入了解分布式系统中常用的一致性哈希算法

  • 傅里叶变换公式整理

    傅里叶变换公式整理1、一维傅里叶变换1.1一维连续傅里叶变换正变换:F(ω)=∫−∞∞f(t)⋅e−iωtdtF(\omega)=\int_{-\infty}^{\infty}f(t)\cdote^{-i\omegat}dtF(ω)=∫−∞∞​f(t)⋅e−iωtdt逆变换:f(t)=∫−∞∞F(ω)⋅eiωtdωf(t)=\int_{-\infty}^{\infty}F(\o…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号