Spring Data JPA使用及实现原理总结

 Spring Data JPA系列

1、SpringBoot集成JPA及基本使用

2、Spring Data JPA Criteria查询、部分字段查询

3、Spring Data JPA数据批量插入、批量更新真的用对了吗

4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作

5、Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用

6、【源码】Spring Data JPA原理解析之Repository的自动注入(一)

7、【源码】Spring Data JPA原理解析之Repository的自动注入(二)

8、【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码

9、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)

10、【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)

11、【源码】Spring Data JPA原理解析之Repository自定义方法添加@Query注解的执行原理

12、【源码】SpringBoot事务注册原理

13、【源码】Spring Data JPA原理解析之事务注册原理

14、【源码】Spring Data JPA原理解析之事务执行原理

15、【源码】SpringBoot编程式事务使用及执行原理

16、【源码】Spring事务之传播特性的详解

17、【源码】Spring事务之事务失效及原理

18、【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理

19、【源码】Spring Data JPA原理解析之Auditing执行原理

20、Spring Data JPA使用及实现原理总结

前言

《 Spring Data JPA系列》博文已经写了19篇,对于Spring Data JPA,还有其他的知识点,该系列博文暂时先写这些。该系列从入门到高级、再到源码解读,分享了Spring Data JPA在开发中最常用的技术点和实现原理。本篇对《Spring Data JPA系列》做一个总结。

Spring Data JPA简介

Spring Data JPA是Spring提供的一套简化JPA开发的框架,按照约定好的方法名命规则写DAO层接口,可以在不写接口实现的情况下,实现对数据库中Table的操作,同时提供了除CRUD操作之外的许多功能,如分页、复杂查询等。

Repository接口类型

在JPA中,通过自定义Repository接口,实现对数据库的操作。Repository接口的接口方法类型为以下三类:

1)第一类Repository接口为继承JpaRepositoryImplementation接口的接口方法,该接口提供并自动实现了对实体类的CRUD等的操作;

2)通过方法命名规则,自定义接口方法,无需写SQL或HQL,实现数据库表的操作,主要针对数据库表的查询、删除操作;

方法名称规则:

操作(关键字)+ By + 属性名称(属性名称的首字母大写)+ 查询条件(首字母大写)

操作关键字包括:

find | read | get | query | search | stream | count | exists | delete | remove

查询条件包括:

And | Or | Is | Equals | Between | LessThan | Before | LessThanEqual | GreaterThan | After | GreaterThanEqual | IsNull | IsNotNull | NotNull | Like | NotLike | StartingWith | EndingWith | Containing | OrderBy | Not | In | NotIn | True | False | IgnoreCase | OrderBy

3)通过@Query注解,添加SQL或HQL,自定义接口方法,实现数据库表的操作;

在@Query注解中,支持三类查询语句的书写形式,分别如下:

a)通过@Query注解的value属性,填写HQL语句;

b)通过@Query注解的value属性,填写SQL语句,nativeQuery属性设置为true;

c)通过@Query注解的name属性,填写对应的queryName。其中:queryName为在实体类中,通过@NamedQueries、@NamedQuery注解添加的HQL语句;

详见:SpringBoot集成JPA及基本使用-CSDN博客

EntityManager实现的数据库操作

在JPA中,除了通过Repository接口实现对数据库的操作以外,还可以通过EntityManager编码,实现数据库操作。

Java Persistence API(JPA)中的EntityManager是一个接口,在JPA规范中,EntityManager扮演着执行持久化操作的关键角色。普通Java对象只有被EntityManager持久化之后,才能转变为持久化对象,保存到数据库中。它不仅可以管理和更新Entity对象,还可以基于主键查询Entity对象,通过JPQL语句进行Entity查询,甚至通过原生SQL语句进行数据库更新及查询操作。

EntityManager提供以下功能:

1)创建、更新和删除数据:EntityManager中的persist()、merge()和remove()方法分别用于插入、更新和删除数据库记录;

2)查询数据:EntityManager的find()和createQuery()方法用于查询数据;

3)管理实体的生命周期:EntityManager的flush()方法用于将持久性上下文同步到基础数据库,进行持久化操作;

4)事务管理:EntityManager的getTransaction()方法用于获取当前事务,可以对事务进行提交或回滚;

5)执行原生SQL:EntityManager的createNativeQuery()方法用于执行原生SQL。对于原生SQL,需要考虑不同数据库的各自实现;

6)创建CriteriaBuilder:EntityManager的getCriteriaBuilder()方法用于获取CriteriaBuilder。通过CriteriaBuilder实现使用Criteria API查询数据;

详见:Spring Data JPA数据批量插入、批量更新真的用对了吗-CSDN博客

Criteria查询

JPA的Repository接口操作数据库时,无法很好的支持动态条件查询,Criteria查询可以很好的解决这个问题。

Criteria查询的API主要包括:

1)CriteriaBuilder:用于构造条件查询、复合选择、表达式、谓词和排序;

2)CriteriaQuery:定义了特定于顶级查询的功能,包含了查询的各个部分。如:select结果集、where条件、group by、order by等。在CriteriaQuery指定返回值结果集;

3)Root:定义Criteria查询的根对象,Criteria查询的根定义为实体类型,它与SQL查询中的FROM子句类似,定义了查询的FROM子句中能够出现的类型。可以有多个查询根对象;

4)Expression:运算表达式。用在查询语句的select、where和having子句中,该接口有isNull、isNotNull和in方法。可通过Root.get(“实体类属性”)获得Expression对象;

5)Predicate:过滤条件。通过CriteriaQuery.where()方法,将Predicate或Expression实例作为条件应用到Criteria查询中;

Predicate实例可以通过CriteriaBuilder的条件方法(equal、notEqual、gt、ge、lt、le、between、like等)创建;

Predicate实例也可以通过Expression实例的isNull、isNotNull和in方法获得;

复合的Predicate语句,可以使用CriteriaBuilder的and、or、andnot方法构建;

详见:Spring Data JPA Criteria查询、部分字段查询-CSDN博客

JPA多表关系

在JPA中,支持多表关系定义及多表级联操作。

多表关系主要相关注解:

@OneToOne注解:表示一对一关系;

@OneToMany、@ManyToOne注解:表示一对多关系;

@ManyToMany注解:表示多对多关系;

@JoinColumn注解:标记实体类与数据库的对应关系,以@OneToOne、@OneToMany、@ManyToOne三个注解搭配使用;

@JoinTable注解:多对多通常使用中间表关联,通过该注解标记关联表,以@ManyToMany注解搭配使用。属性name为关联表的名称、joinColumns为关联student表的id、inverseJoinColumns为关联Course表的id;

多表级联操作是指当一个实体的状态发生改变时,关联的其他实体是否同时发生改变。简单理解:cascade用于设置当前实体是否能够操作关联的另一个实体的权限。cascade的取值在CascadeType枚举类中定义。

详见:Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作

实体类Id生成策略

JPA默认支持四种Id生成策略,分别为TABLE(使用数据库表格保存主键)、SEQUENCE(使用底层数据库的序列来生成主键)、IDENTITY(主键由数据库自动生成)、AUTO(主键由程序控制)。通过@GeneratedValue注解中的strategy属性指定对应生成策略。

除了以上四种默认支持的策略以外,JPA还支持自定义Id生成策略,通过实现org.hibernate.id.IdentifierGenerator接口,重写generate()方法,在方法中返回Id值。

通过@GenericGenerator注解,指定自定义Id策略的名称name及对应的策略strategy的类,并添加@GeneratedValue注解的generator属性为@GenericGenerator注解的name属性。

复合主键

在Spring Data JPA的实体类中并不支持简单的直接在多个属性中添加@Id注解实现复合主键。而是需要先创建一个复合主键类,然后在实体类中使用@IdClass注解将主键类附加在类中,然后在多个主键属性中添加@Id主键。

Auditing审计

JPA通过@CreateBy、@CreateDate、@LastModifiedBy、@LastModifiedDate四个注解,提供对数据库表中的数据记录自动添加操作人及操作时间的审计功能。

在实际开发中,可以定义一个抽象父类,专门记录操作人及操作信息。在该父类中添加@MappedSuperclass注解。

Auditing使用

1)在启动类中添加@EnableJpaAuditing注解,开启Auditing;

2)在实体类中添加监听器及操作人、操作时间的注解。或者定义一个抽象父类,专门记录操作人及操作信息。并添加@EntityListeners注解,添加AuditingEntityListener监听器;

3)自定义AuditorAware,重写getCurrentAuditor(),返回审计员主键,实现数据记录的创建人、操作人的自动填充;

详见:Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用-CSDN博客

Repository自动注入原理

JPA的Repository注入到Spring IOC容器的对象为代理对象,其中target为SimpleJpaRepository对象,实现了自定义的Repository接口、Repository接口以及TransactionProxy接口,主要添加了QueryExecutorMethodInterceptor、TransactionInterceptor等拦截器。

注入的主要执行流程如下:

1)在SpringBoot中引入spring-boot-starter-data-jpa依赖时,会自动注入JpaRepositoriesAutoConfiguration,从而注入JpaRepositoryConfigExtension;

2)在JpaRepositoryConfigExtension的父类RepositoryConfigurationExtensionSupport的getRepositoryConfigurations()方法中,获取所有实现Repository接口的类,封装成RepositoryConfiguration;

3)SpringBoot启动时,会执行RepositoryConfigurationDelegate的registerRepositoriesIn()方法,在该方法中,获取2)中所有实现Repository接口的类,创建对应的BeanDefinition对象,其中beanClass为"org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean"字符串。并执行registry.registerBeanDefinition(beanName, beanDefinition),将Repository类及对应的beanDefinition添加到Spring IOC容器中;

4)在Spring启动过程中,会执行AbstractBeanFactory.doGetBean()方法,先从Repository的BeanDefinition中,获取beanClass,为JpaRepositoryFactoryBean类名,然后创建JpaRepositoryFactoryBean对象。执行afterPropertiesSet()方法,完成初始化;

5)在JpaRepositoryFactoryBean的afterPropertiesSet()初始化方法中,会调用RepositoryFactorySupport.getRepository()方法。该方法通过代理的的方式,创建一个实现了自定义的Repository接口、Repository以及TransactionProxy接口,且代理的target为SimpleJpaRepository对象,代理添加了QueryExecutorMethodInterceptor、TransactionInterceptor等拦截器。代理的对象保存在repository属性中;

6)执行了JpaRepositoryFactoryBean对象的afterPropertiesSet()初始化之后,会调用AbstractBeanFactory.getObjectForBeanInstance(),从JpaRepositoryFactoryBean工厂bean中执行getObject(),返回创建的代理repository对象;

详见:

【源码】Spring Data JPA原理解析之Repository的自动注入(一)-CSDN博客

【源码】Spring Data JPA原理解析之Repository的自动注入(二)-CSDN博客

提醒:最好指定Repository所在的包,以免扫描整个SpringBoot启动类所在的包及其子包来获取Repository类

Repository接口实现原理

Repository在Spring容器中为代理对象,Repository接口的接口方法有三种类型,其实现原理分别为:

11.1)继承JpaRepositoryImplementation接口的接口方法

在Repository代理对象中,target为SimpleJpaRepository对象。该对象实现了JpaRepositoryImplementation接口。

当执行JpaRepositoryImplementation接口中的方法时,在动态代理中,会调用执行SimpleJpaRepository的对应方法。

在SimpleJpaRepository中,通过EntityManager接口及Criteria查询接口实现了对数据库的相关操作。

详见:

【源码】Spring Data JPA原理解析之Repository执行过程及SimpleJpaRepository源码

11.2)通过方法命名规则

通过方法命名规则,自定义接口方法的实现是通过Repository代理对象中的QueryExecutorMethodInterceptor拦截器中实现的。

主要执行流程如下:

1)QueryExecutorMethodInterceptor方法拦截器的构造方法中,会根据查询查找策略CreateIfNotFoundQueryLookupStrategy,获得RepositoryQuery对象,解析方法。对于按方法命名规则实现的方法,使用的RepositoryQuery对象为PartTreeJpaQuery;

2)在PartTreeJpaQuery构造方法中,创建一个PartTree对象,解析方法名称中的起始关键字【如:findBy、readBy、deleteBy等】、条件属性【实体类中的属性】、查询关键字【Between、In、Equals等】;

3)创建对应方法的countQuery和query,将解析出的查询的基础信息封装在QueryPreparer对象中,根据解析出的查询信息,创建CriteriaQuery对象;

4)解析完方法信息,保存在PartTreeJpaQuery后,保存到QueryExecutorMethodInterceptor的Map<Method, RepositoryQuery> queries中;

5)当Repository的接口被调用的时候,在ReflectiveMethodInvocation.proceed()中,先执行QueryExecutorMethodInterceptor.invoke()方法;

5.1)调用doInvoke()方法,获取数据库执行后的数据;

5.1.1)调用RepositoryQueryMethodInvoker.invoke() -> RepositoryQuery.execute() -> AbstractJpaQuery.execute() -> AbstractJpaQuery.doExecute() -> JpaQueryExecution.execute() -> JpaQueryExecution.doExecute();

5.1.2)doExecute()是一个抽象方法,针对不同的数据库查询返回值信息,使用不同的实现类。所有的实现类都会先调用AbstractJpaQuery.createQuery(),获取一个Query对象;

5.1.3)在AbstractJpaQuery.createQuery()中,调用抽象方法doCreateQuery()。对于按方法命名规则的Repository接口,实现类为PartTreeJpaQuery;

5.1.4)在PartTreeJpaQuery.coCreateQuery()方法中,通过EntityManager.createQuery(criteriaQuery)返回TypedQuery,然后执行invokeBinding(),在TypedQuery对象中,调用query.setParameter()绑定查询条件的参数值,如果有分页,设置分页信息;

5.1.5)参数完参数,在6.1.3中设置hint等。然后执行6.1.2中的具体实现类,执行数据库查询。如SingleEntityExecution实现类,执行TypeQuery.getSingleResult(),然后单个结果;

5.2)调用resultHandler.postProcessInvocationResult(),对数据库查询后的值进行返回值类型转换;

详见:

【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)

【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(二)

11.3)通过@Query注解

通过@Query注解,添加SQL或HQL,自定义接口方法的实现也是通过Repository代理对象中的QueryExecutorMethodInterceptor拦截器中实现的。对比方法命名规则的实现,差异在于使用不同的查询解析方法。

主要执行流程如下:

1)QueryExecutorMethodInterceptor方法拦截器的构造方法中,会根据查询查找策略CreateIfNotFoundQueryLookupStrategy,获得RepositoryQuery对象,解析方法。对于添加@Query注解的方法,使用的RepositoryQuery对象为SimpleJpaQuery和NativeJpaQuery;

2)SimpleJpaQuery和NativeJpaQuery都是继承AbstractStringBasedJpaQuery,在AbstractStringBasedJpaQuery构造方法中,解析对应的queryString和countQueryString,生成DeclaredQuery对象,实际对象为ExpressionBasedStringQuery。核心的解析过程在父类StringQuery中;

3)解析完方法信息,保存在父类AbstractStringBasedJpaQuery后,保存到QueryExecutorMethodInterceptor的Map<Method, RepositoryQuery> queries中;

4)当Repository的接口被调用的时候,在ReflectiveMethodInvocation.proceed()中,先执行QueryExecutorMethodInterceptor.invoke()方法;

4.1)调用doInvoke()方法,获取数据库执行后的数据;

4.1.1)调用RepositoryQueryMethodInvoker.invoke() -> RepositoryQuery.execute() -> AbstractJpaQuery.execute() -> AbstractJpaQuery.doExecute() -> JpaQueryExecution.execute() -> JpaQueryExecution.doExecute();

4.1.2)doExecute()是一个抽象方法,针对不同的数据库查询返回值信息,使用不同的实现类。所有的实现类都会先调用AbstractJpaQuery.createQuery(),获取一个Query对象;

4.1.3)在AbstractJpaQuery.createQuery()中,调用抽象方法doCreateQuery()。对于添加@Query注解Repository接口,实现类为SimpleJpaQuery或NativeJpaQuery,方法实现在父类AbstractStringBasedJpaQuery.doCreateQuery();

4.1.4)在AbstractStringBasedJpaQuery.doCreateQuery()方法中,通过EntityManager.createQuery(queryString)返回Query【如果是NativeJpaQuery,使用EntityManager.createNativeQuery(queryString)返回Query】,然后执行invokeBinding(),在Query对象中,调用query.setParameter()绑定查询条件的参数值,如果有分页,设置分页信息;

4.1.5)参数完参数,在6.1.3中设置hint等。然后执行6.1.2中的具体实现类,执行数据库查询。如SingleEntityExecution实现类,执行TypeQuery.getSingleResult(),然后单个结果;

4.2)调用resultHandler.postProcessInvocationResult(),对数据库查询后的值进行返回值类型转换;

Auditing审计实现原理

JPA接口中提供了持久化的监听回调注解,通过添加注解,可以监听实体的新增、修改、删除的前后状态。

主要执行流程如下:

1)JPA的提供了持久化的监听回调注解;

2)Spring解析实体类时,会解析实体类中添加的监听回调注解的监听器;或者实体类中的@EntityListeners注解中的监听器,并归类存放在FastSessionServices中,然后将FastSessionServices传给SessionImpl对象。对于Auditing,监听器为AuditingEntityListener,添加了@PrePersist和@PreUpdate,在新增和修改之前回调。

3)Auditing审计功能通过添加@EnableJpaAuditing注解,自动为AuditingEntityListener添加AuditHandler对象;

4)AuditHandler对象提供了对当前执行持久化对象的审计相关注解的属性获取、审计人获取;

5)JPA通过SessionImpl执行新增或修改操作时,会调用FastSessionServices中对应操作类型的监听器,从而执行AuditingEntityListener的方法;

6)AuditingEntityListener通过AuditHandler及当前的实体类,通过反射,为实体类的审计属性赋值;

详见:

【源码】Spring Data JPA原理解析之Hibernate EventListener使用及原理-CSDN博客

【源码】Spring Data JPA原理解析之Auditing执行原理-CSDN博客

JPA事务

12.1)事务说明

事务是指在数据库管理系统中,一系列紧密相关的操作序列,这些操作作为一个单一的工作单元执行。事务的特点是要么全部成功,要么全部失败,不会出现部分完成的情况。如果事务中的任何一个操作失败,那么整个事务都会被回滚到开始之前的状态,以确保数据库的一致性和完整性。

事务的四个特性为:原子性、一致性、隔离性和持久性。通常称为ACID。

在Spring框架中,数据操作的事务是通过添加@Transactional注解来实现的。

12.2)JPA事务实现原理

JPA的Repository注入到Spring IOC容器的对象为代理对象,其中添加了TransactionInterceptor拦截器,在该拦截器中实现了事务。

主要执行流程如下:

1)当方法调用时,执行TransactionInterceptor.invoke()方法,该方法调用父类TransactionAspectSupport.invokeWithinTransaction()方法;

2)解析原方法的@Transactional注解信息,封装为TransactionAttribute对象;

3)从Spring容器中获取JpaTransactionManager对象;

4)根据传播特性,选择性开启事务;

5)在try中执行ReflectiveMethodInvocation.proceed()方法,直至执行原方法,获取返回值;

6)在catch中捕获异常,如果出现异常,执行completeTransactionAfterThrowing(),对满足回滚规则的,执行回滚;如果不满足回滚规则,依然提交事务,并抛出异常,结束方法;

7)如果没有异常,提交事务;

详见:

【源码】Spring Data JPA原理解析之事务注册原理-CSDN博客

【源码】Spring Data JPA原理解析之事务执行原理-CSDN博客

【源码】Spring事务之传播特性的详解-CSDN博客

12.3)事务失效

事务使用不当时,可能导致事务失效。常见的事务失效场景如下:

1)访问权限问题。非public访问权限的方法,即使添加了@Transactional注解,事务无效;

2)无效异常。Spring事务回滚是通过异常捕获实现的,默认只处理RuntineException或Error异常,也可以通过@Transactional的rollbackFor参数设置回滚异常;

3)业务异常捕获。如果在业务中捕获了异常,Spring事务无法捕获到异常,回滚失效。需要通过TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(),设置回滚状态;

4)内部方法调用。在一个上下文没有事务的方法中,通过this调用内部添加@Transactional注解的方法时,事务无效。因为此时的this是目标对象,不是对应的代理对象;

5)传播特性使用不当。

6)异步线程调用。事务信息是通过ThreadLocal保存在本地线程变量中,对于异步线程无效;

详见:

【源码】Spring事务之事务失效及原理-CSDN博客

【源码】Spring事务之传播特性的详解-CSDN博客

JPA的优点与缺点

13.1)优点

1)简化数据持久化操作:JPA框架提供了一系列的API和工具,提供实体的CRUD方法,减少SQL语句的编写,开发效率高;

2)可移植性好:JPA框架是基于对象关系映射(ORM)的规范,底层采用Hibernate,提供标注的查询语言,对象化程度更好,使得开发人员可以更加方便地切换不同的数据库;

13.2)缺点

1)性能问题:通过源码篇能够了解到,JPA框架提供了较为复杂的对象关系映射机制,可能会影响系统的性能;

2)灵活性较差:JPA强调对象模型和数据库模型的映射,对于复杂的SQL操作,可能需要使用Criteria API或转为Native SQL;

结尾

以上为本篇分享的全部内容。

关于本篇内容你有什么自己的想法或独到见解,欢迎在评论区一起交流探讨下吧。

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

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

相关文章

【数智化人物展】法大大黄翔:从他山之石看中国企业数智化升级的机会点

黄翔 本文由法大大创始人兼CEO黄翔投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着AI、云计算、大数据等技术的飞速发展&#xff0c;数智化转型升级已是全球企业的共识…

css flex 子元素溢出时,父元素被撑开解决方案

当父元素使用flex: 1;自适应填满时&#xff0c;子元素内容溢出&#xff0c;父元素内容撑大&#xff0c;导致页面显示问题&#xff0c;或设置了overflow 为scroll 的元素没出现滚动条等问题 解决方案&#xff1a; 1.如果是横向排列&#xff0c;flex: 1;的元素加上width: 0; 此…

调整分区失败致盘无法访问:深度解析与数据恢复全攻略

调整分区失败盘打不开的困境 在计算机的日常维护与管理中&#xff0c;调整磁盘分区是常见的操作之一&#xff0c;旨在优化存储空间布局、提升系统性能或满足特定应用需求。然而&#xff0c;当这一操作未能如预期般顺利进行&#xff0c;反而导致分区调整失败&#xff0c;进而使…

模拟算法系列|替换所有的问号|提莫攻击|种花问题|Z字形变换|兼具大小写的英文字母|删除字符使频率相同

大家好,我是LvZi,今天带来模拟算法系列|替换所有的问号|提莫攻击|种花问题|Z字形变换|兼具大小写的英文字母|删除字符使频率相同 一.基本概念 模拟算法就是根据题意 模拟出代码的过程,模拟算法的题意往往都很简单,考验的是将思路转化为代码的能力,十分的锻炼代码能力,且能很好…

【日记】在街上跳舞被同事看见了(470 字)

正文 昨晚跳舞&#xff0c;照例在街上表演&#xff0c;被单位里的保洁阿姨撞见了…… 我以为这就完了&#xff0c;结果她还拍了视频发给做饭阿姨。晚上吃饭无意间聊起才知道有这回事。我竟一时间不知该哭还是该笑……. 今天非常非常闲。虽然不是没工作&#xff0c;只是我懒得去…

pdf转图片

前提 环境ubuntu22.04 lts,windows没有测试过。 今天想用wps pdf转换一下为图片,发现要收费!!!!为了省钱,只好撸代码了。说实话,这年头赚钱真的不容易,特别是程序员,但是我是一个运维也算半个程序员。 pip install pdf2image sudo apt-get install poppler-utils代…

418天内第6次发布,科大讯飞星火大模型在跟谁赛跑?

常言道“一步慢&#xff0c;步步慢”&#xff0c;大模型市场瞬息万变&#xff0c;快人一步就是竞争的反转。 6月27日&#xff0c;科大讯飞如期公布星火大模型的最新进展&#xff1a;大模型底座七大核心能力得到全面提升&#xff0c;星火大模型V4.0可对标GPT-4 Turbo&#xff0…

C# Opacity 不透明度

WinForms Opacity以下是一些使用 Opacity 属性的示例&#xff1a;设置窗体的透明度&#xff1a;设置按钮的透明度&#xff1a;动态改变控件的透明度&#xff1a;使用定时器改变透明度&#xff1a;在窗体加载时设置透明度&#xff1a; 请注意另外 WPF Opacity以下是一些使用 Opa…

软考系统架构师高效备考方法论

软考系统架构师高效备考方法论 本章总结的备考方法论也是希望能帮助更多的小伙伴高效的备考最终通过考试&#xff0c;这种考试个人感觉是尽量一次性考过&#xff0c; 要不然老拖着&#xff0c;虽然每年可以考两次&#xff0c;5月和11月&#xff0c;两次考试间隔5个月时间&#…

ELK日志实时监控

目录 一、ELK/EFK简介 1.1 什么是ELK/EFK? 1.2 常见架构 1、Elasticsearch Logstash Kibana 2、Elasticsearch Logstash Filebeat Kibana 3、Elasticsearch Logstash Filebeat Kibana Redis 4、Elasticsearch Fluentd Filebeat Kibana 1.3 基本流程 二、…

JVM专题之垃圾收集算法

标记清除算法 第一步:标记 (找出内存中需要回收的对象,并且把它们标记出来) 第二步:清除 (清除掉被标记需要回收的对象,释放出对应的内存空间) 缺点: 标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需 要分配较大对象时,无法找到…

反射--通俗易懂

一、反射(Reflection) 反射就是:加载类&#xff0c;并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等) 动态语言&#xff0c;是一类在运行时可以改变其结构的语言&#xff1a;例如新的函数、对象、甚至代码可以被引进&#xff0c;已有的函数可以被删除或是其他…

多重奖励拿到手软,OPENAIGC开发者大赛燃爆这个夏天!

你是否渴望在AI领域一展身手&#xff1f; 你是否拥有开创性的技术和创意&#xff1f; 2024 OPENAIGC开发者大赛就是你的最佳舞台&#xff01; 不论你是经验丰富的开发者&#xff0c; 还是技术领域的创新者&#xff0c; 都有机会在这里大放异彩&#xff01; 由联想拯救者、…

每日一题 7月1日

1 设数组data[m]作为循环队列的存储空间,front为队头指针,rear为队尾指针,则执行出队操作后其头指针front值为____ 2 采用滑动窗口机制对两个相邻结点A(发送方)和B(接收方)的通信过程进行流量控制。假定帧的序号长度为3比特,发送窗口与接收窗口的大小均为7,当A发送了…

分析Profiler Timeline中的算子序列,通过寻找频繁项集的办法,得到TOPK可融合的算子序列

分析Profiler Timeline中的算子序列,通过寻找频繁项集的办法,得到TOPK可融合的算子序列 1.相关链接2.代码【仅分析带通信算子的Pattern】3.在实际工程中发现 [all_gather, matrix_mm_out]频率最高4.[Ascend MC2](https://gitee.com/ascend/MindSpeed/blob/master/docs/features…

1:25万基础电子地图(西藏版)

我们为你分享过四川版、云南版、江西版、贵州版、重庆版和青海版的1比25万基础电子地图&#xff0c;现在再为你分享西藏版的电子地图。 如果你需要西藏版的1比25万基础电子地图&#xff0c;你可以在文末查看该数据的领取方法。 基础电子地图西藏版 西藏版1:25万基础电子地图…

go框架gin自定义和增强*gin.Context的方法 --使用闭包函数将自定义Context handler转换为 gin.HandlerFunc

在使用gin框架进行开发的时候&#xff0c;我们可以通过自定义gin.Context来实现和增强gin框架&#xff0c;方法也很简单&#xff0c;关键就2个步骤&#xff0c; 1是继承gin.Context&#xff0c; 2是在路由的时候对函数入参类型进行转换&#xff0c;下面为具体的方法&#xff1a…

压缩pdf文件大小,压缩pdf文件大小软件哪个好

在数字化时代&#xff0c;PDF文件因其卓越的跨平台兼容性和稳定性而成为工作与学习的好帮手。然而&#xff0c;当PDF文件体积过大时&#xff0c;传输和存储便成了一项挑战。别担心&#xff0c;本文将为你揭秘如何快速压缩PDF文件&#xff0c;让你的文档轻装上路&#xff01; 压…

postman请求访问:认证失败,无法访问系统资源

1、使用postman时&#xff0c;没有传入相应的token&#xff0c;就会出现这种情况&#xff0c;此时需要把token放进去 发现问题: { "msg": "请求访问&#xff1a;/getInfo&#xff0c;认证失败&#xff0c;无法访问系统资源", "code": 401 } 1…

从美图类场景,看火山引擎数据飞轮如何赋能产品增长

伴随移动移动互联网发展以及手机拍摄能力提升&#xff0c;美图类APP已成为人们手机中常见的应用之一。根据广发证券发展研究中心《数字媒体行业AI系列报告&#xff1a;美图类APP&#xff0c;商业模式逐渐清晰&#xff0c;AIGC加速付费心智培养》显示&#xff0c;从行业整体流量…