• [技术干货] 为什么数据库要允许没有主键的表存在
    在数据库设计中,主键是一个关键概念,用于唯一标识数据库表中的每一行数据。然而,有时候数据库允许没有主键的表存在的情况,这可能会引起一些争议和疑问。本文将探讨为什么数据库允许没有主键的表以及相关的考虑因素。1. 定义主键的作用主键在数据库中具有以下作用:唯一标识数据:主键保证每一行数据的唯一性,确保不会存在重复的数据。快速检索:主键字段上的索引能够提高数据检索的性能,加快查询速度。建立关系:主键可以与其他表建立关联关系,实现表之间的关联和数据一致性。2. 允许没有主键的表的原因虽然主键在大多数情况下是必要的,但数据库允许没有主键的表存在的原因如下:2.1. 数据完整性由应用程序保证有时候,应用程序会在数据层面保证数据的完整性,而不是依赖数据库层面的主键约束。这样做的原因可能是为了更好地控制数据逻辑和业务流程。在这种情况下,数据库允许没有主键的表存在,将完整性的责任交给了应用程序。2.2. 数据库设计灵活性需求某些特定的数据库设计场景可能要求灵活性,而不需要主键。例如,日志表、临时表或其他非常规数据存储场景可能不需要主键。这些表可能被频繁写入和删除,并且主要用于数据临时存储或分析,而不需要进行常规的数据操作。2.3. 大规模数据集的性能优化在处理大规模数据集时,主键的维护和索引可能会对性能产生一定影响。为了获得更好的性能,某些场景下可能会选择不使用主键。这种情况下,数据库管理员需要根据实际情况进行权衡,平衡性能和数据完整性之间的关系。3. 注意事项和风险尽管数据库允许没有主键的表存在,但需要注意以下事项和风险:数据重复和数据不一致:没有主键的表可能出现数据重复或数据不一致的情况。在没有主键的情况下,需要由应用程序来保证数据的唯一性和一致性,否则可能导致数据混乱和错误。查询性能下降:没有主键的表上的查询性能可能受到影响,特别是在没有适当的索引支持的情况下。如果频繁进行数据检索操作,可能需要考虑添加合适的索引来提高性能。4. 总结数据库允许没有主键的表存在是出于灵活性、性能优化或特定设计需求等考虑。然而,需要认识到没有主键的表可能会带来数据完整性和查询性能的问题。在设计数据库时,应根据具体场景和需求来决定是否需要主键,并权衡性能和数据一致性之间的关系。在没有主键的情况下,应用程序需要负责保证数据的唯一性和一致性,以避免数据问题的出现。
  • [技术干货] HttpClient最丰富和灵活的版本
    // Java 8 and earlier import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; public class Main { public static void main(String[] args) throws IOException { URL url = new URL("https://www.example.com"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); int status = con.getResponseCode(); System.out.println(status); } } // 优点:简单易用。缺点:功能有限,不够灵活。 // Java 8 import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Main { public static void main(String[] args) throws IOException, InterruptedException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.example.com")) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); } } // 优点:比Java 8和之前的版本具有更多的功能和灵活性。缺点:仍然缺少一些高级功能。 // Java 9 import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Main { public static void main(String[] args) throws IOException, InterruptedException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.example.com")) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); } } // 优点:添加了Java 8中缺少的一些功能。缺点:仍然不如Java 11功能丰富。 // Java 11 import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class Main { public static void main(String[] args) throws IOException, InterruptedException { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.example.com")) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); } } // 优点:HttpClient最丰富和灵活的版本。缺点:需要Java 11或更高版本。​
  • [技术干货] 实现高并发秒杀的7种方式 建议收藏!!
    延迟加载:// 将商品信息加载到缓存中 public void loadGoodsToCache() { List<Goods> goodsList = goodsService.getGoodsList(); for (Goods goods : goodsList) { redisTemplate.opsForValue().set("goods:" + goods.getId(), goods); } } // 秒杀开始时将缓存中的商品信息加载到数据库中 public void startSeckill() { List<Goods> goodsList = redisTemplate.opsForValue().multiGet(redisTemplate.keys("goods:*")); for (Goods goods : goodsList) { goodsService.updateGoods(goods); } }队列:java // 将秒杀请求放入消息队列中 public void seckill(String userId, String goodsId) { SeckillRequest request = new SeckillRequest(userId, goodsId); rabbitTemplate.convertAndSend("seckill.exchange", "seckill.queue", request); } // 消费者处理秒杀请求 @RabbitListener(queues = "seckill.queue") public void handleSeckillRequest(SeckillRequest request) { // 处理秒杀请求 }限流:java // 使用Guava RateLimiter进行限流 private static final RateLimiter rateLimiter = RateLimiter.create(100); // 处理秒杀请求 public void seckill(String userId, String goodsId) { if (rateLimiter.tryAcquire()) { // 处理秒杀请求 } else { // 返回错误信息 } }分布式锁:java // 使用Redisson实现分布式锁 private static final RLock lock = redissonClient.getLock("seckill"); // 处理秒杀请求 public void seckill(String userId, String goodsId) { try { lock.lock(); // 处理秒杀请求 } finally { lock.unlock(); } }CDN加速:java // 使用Nginx配置CDN加速 location /static/ { proxy_pass http://cdn.example.com/static/; }分布式缓存:java // 使用Redis缓存商品信息 public Goods getGoodsById(String goodsId) { Goods goods = redisTemplate.opsForValue().get("goods:" + goodsId); if (goods == null) { goods = goodsService.getGoodsById(goodsId); redisTemplate.opsForValue().set("goods:" + goodsId, goods); } return goods; }异步处理:java // 将秒杀请求放入消息队列中,由异步处理程序进行处理 public void seckill(String userId, String goodsId) { SeckillRequest request = new SeckillRequest(userId, goodsId); rabbitTemplate.convertAndSend("seckill.exchange", "seckill.queue", request); } // 异步处理程序处理秒杀请求 @RabbitListener(queues = "seckill.queue") public void handleSeckillRequest(SeckillRequest request) { // 处理秒杀请求 }​​
  • [技术干货] 模式和用户的关系
    模式和用户的关系在数据库中,一个用户可以拥有一个或多个模式的访问权限,而每个模式可能包含不同的数据库对象,例如表、视图、索引等。简单来说,一个模式定义了一组相关的数据库对象,而一个用户则授权访问这些对象的权限。通常情况下,每个数据库系统都会默认创建一个公共的模式,称为“公共模式”(public schema),该模式存储所以用户都可见和访问的公共对象。此外,还可以为每个用户创建独立的模式,这样每个用户就可以拥有自己的私有对象,而不与其他用户的对象混合在一起。简而言之,用户和模式之间的关系是通过授权来实现的。一个用户必须具备访问某个模式的权限才能够查看和操作其中的对象。多个用户可以共享同一个模式,而同一个用户也可以拥有访问多个模式的权限。为什么我创建完成用户,生成了一个默认的模式在大多数关系型数据库中,一个用户默认会有一个与其同名的模式,而这个模式是该用户所拥有的所有对象的默认存储位置。这样做的好处在于可以将不同用户的数据分开存放,以保证数据隔离性和安全性。同时也方便用户管理自己所拥有的对象。需要注意的是,并非所有数据库都支持这种默认创建模式的方式,每种数据库实现的细节可能略有不同。怎么删除模式内的内容在大多数关系型数据库中,你可以使用 `DROP` 语句来删除模式内的内容。具体而言,可以使用以下命令来删除模式内的表:DROP TABLE schema_name.table_name;其中,`schema_name` 是指要删除表所属的模式名称,`table_name` 是需要删除的表的名称。如果要删除模式内的其他类型对象,例如视图、索引、函数等,可以使用对应的 DROP 语句,如下所示:- 删除视图:`DROP VIEW schema_name.view_name;`- 删除索引:`DROP INDEX schema_name.index_name;`- 删除函数:`DROP FUNCTION schema_name.function_name;`- 删除存储过程:`DROP PROCEDURE schema_name.procedure_name;`需要注意的是,删除模式内的某个对象将永久地从数据库中移除该对象,因此在执行这些操作之前,请务必确认自己的选择并进行备份,防止误删造成不可恢复的损失。此外,删除对象的权限也是需要谨慎考虑的,以确保系统安全和稳定性。
  • [技术干货] 数据库中模式的概念
    在数据库中,模式(Schema)是一种逻辑结构,用来描述数据库对象(如表、视图、索引等)之间的组织关系和访问权限。模式定义了实体的类型、它们之间的联系及其属性和约束。一个数据库系统中可以有多个不同的模式,每个模式又可以含有多个表或其他的数据库对象。一般来说,每个模式都有一个名称,以便区分不同的模式。模式还可以定义给定数据库对象的访问控制级别,包括读写权限和限制对数据和表的修改权限。通过使用模式,可以使数据库的管理更加容易和清晰,同时允许用户隔离各自的数据库对象并独立管理它们。
  • [开发应用] opengauss2.1数据库的字段名是大写,程序查找时显示小写字段不存在
    opengauss2.1数据库的字段名是大写,程序查找时显示小写字段不存在,能否设置数据库忽略大小写
  • [其他问题] springboot连接opengauss2.1异常PSQLException:Invalid or unsupported by client scram mechanisms
    连接opengauss一直显示PSQLException:Invalid or unsupported by client scram mechanisms该异常
  • [技术干货] 2023年5月论坛问题合集
    1.【GaussDB】GaussDB死元组清理有方法吗?cid:link_02【GaussDB】GaussDB序列函数nextval(regclass)有两种调用方式,性能差异大吗?cid:link_33【GaussDB】GaussDB创建视图后,无法对视图进行删除数据的动作吗?cid:link_44【GaussDB】请问下GaussDB支持INSERT .. ON CONFLICT语法吗?cid:link_55 Huawei Cloud EulerOS 2.0 等保2.0三级版 64位 怎么安装mongodb5cid:link_66 如何实现手机端目标检测cid:link_77 使用mindspore1.7版本跑yolov4时运行失败,日志提示cp: cannot access '/home/ma-user/package/RocksDB': Permission deniedcid:link_88 Atlas200的输入为二维txtcid:link_99 MindSpore框架Yolov3-darknet模型的篮球动作检测训练时报错:当前节点错误:obs请求失败cid:link_110 新建远程链接 无法正常显示 cid:link_1011 如何通过wget下载软件发布库里的文件cid:link_212 网络AI领域10大公开数据集 怎么进入查看和下载 cid:link_11
  • [技术干货] Oracle数据库删除表数据的三种方式
     简介   oracle数据库mysql数据库都是如此 drop命令>truncate命令>delete命令,它们的执行方式、效率和结果各有不同。还是万年的student 学生表 自己可以建个尝试这玩一下。  drop命令 语句:   drop table 表名;  理由:1、用drop删除表数据,不但会删除表中的数据,连结构也会被删除!             2、将被隐式提交。  truncate命令 语句:   truncate  table  表名;  理由:1、用truncate删除表数据,只是删除表中的数据,表结构不会被删除!            2、删除整个表的数据时,过程是系统一次性删除数据,效率比较高            3、truncate删除释放空间             4、将被隐式提交。  delete命令 语句:  delete from 表名; 理由:1、用delete删除表数据,只是删除表中的数据,表结构不会被删除!            2、虽然也是删除整个表的数据,但是过程是系统是一行一行的删,效率也比truncate低            3、delete删除是不释放空间的             4、delete是DML语句,不会自动提交,需手动提交事务。  总结: 1、drop、truncate都是(DDL)语言(数据定义语言),向其他所有的(DDL)语言一样,它将被隐式提交。delete是(DML)语句,不会自动提交。  2、 truncate 和delete 只删除数据不删除表的结构,drop 语句将删除表的结构被依赖的约束(constrain)、触发器(trigger)、索引(index);依赖于该表的存储过程/函数将保留,但是变为invalid (无效)状态。  3、delete 语句是数据库操作语言(DML),这个操作会放到rollback segment 中,事务提交之后才生效;如果有相应的 trigger,执行的时候将被触发。  4、truncate、drop 是数据库定义语言(DDL),操作立即生效,原数据不放到rollback segment 中,不能回滚,操作不触发 trigger。  5、delete 语句不影响表所占用的extent,高水线(high watermark)保持原位置不动、drop 语句将表所占用的空间全部释放。  6、truncate 语句缺省情况下将空间释放到 minextents个extent,除非使用reuse storage;truncate 会将高水线复位(回到最开始)。  7、速度等级分别: drop命令>truncate命令>delete命令  8、实际使用以及安全性:谨慎使用 drop和 truncate,一旦执行没有退步的余地。如想删除部分数据行用 delete加上where条件子句。 想删除表当然是 drop了、想保留表而将所有数据删除,如果和事务无关,用truncate即可。如果和事务有关,或者想触发trigger,还是用delete。如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入或插入数据。   9、truncate  table  表名   在功能上与不带   WHERE   子句的  DELETE   语句相同:二者均可删除表中的全部行。但   truncate  table   比   delete   速度快,且使用的系统和事务日志资源少。   10、delete  语句每次删除一行,并在事务日志中为所删除的每行记录一项。truncate  table   通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。    11、truncate  table   删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用  delete。如果要删除表定义及其数据,请使用   drop  table   语句。     12、对于有   foreign  key   约束引用的表,不能使用  truncate   table,而应使用不带   where   子句的  delete   语句。由于   truncate   table   不记录在日志中,所以它不能激活触发器。      13、truncate  table   不能用于参与索引视图的表。 
  • [其他] 2023.5月合集
    【GaussDB】GaussDB死元组清理有方法吗? https://bbs.huaweicloud.com/forum/thread-02115119067655829007-1-1.html【GaussDB】请问下GaussDB支持INSERT .. ON CONFLICT语法吗?https://bbs.huaweicloud.com/forum/thread-0243118996196808013-1-1.html【GaussDB】GaussDB创建视图后,无法对视图进行删除数据的动作吗?https://bbs.huaweicloud.com/forum/thread-0248118980325040011-1-1.html数字化转型下,我国分布式数据库应用挑战及发展建议https://bbs.huaweicloud.com/forum/thread-0260118919280665012-1-1.htmlhash索引基于什么考虑,不支持范围查询?https://bbs.huaweicloud.com/forum/thread-0232118893298945011-1-1.html为什么频繁更新的列不适合使用索引?https://bbs.huaweicloud.com/forum/thread-0248118893264992006-1-1.htmlmysql 大事务会产生哪些影响? 1)前一张表在做update 同时做了ddl动作会产生什么现象?对后续操作影响吗?https://bbs.huaweicloud.com/forum/thread-0264118893201881008-1-1.html停机不收费!华为云RDS for MySQL降本有奇招https://bbs.huaweicloud.com/forum/thread-0232118919192220013-1-1.html为什么MySQL单表不能超过2000万行?https://bbs.huaweicloud.com/forum/thread-0236119843971206051-1-1.htmlKubernetes YAML文件格式说明https://bbs.huaweicloud.com/forum/thread-0228119861032990050-1-1.htmlOracle数据库删除表数据的三种方式https://bbs.huaweicloud.com/forum/thread-0260119771248192037-1-1.htmljava锁的详解https://bbs.huaweicloud.com/forum/thread-0232120446894808067-1-1.html?fid=565mysql慢查询优化https://bbs.huaweicloud.com/forum/thread-0260120363635166056-1-1.htmlOracle中按天、周、月、季、年统计数据https://bbs.huaweicloud.com/forum/thread-0260119772367102039-1-1.htmlOracle数据库删除表数据的三种方式https://bbs.huaweicloud.com/forum/thread-0260119771248192037-1-1.html
  • [运维管理] GaussDB(DWS)在哪个版本会支持analyze单分区?
    已知8.1.1版本中,analyze支持单分区收集统计信息的语法,但是功能上不支持。那么8.1.3或8.2.1版本中,analyze是否可以支持单分区收集统计信息。
  • [技术干货] openGauss配置文件的备份与恢复
     背景信息 在openGauss使用过程中,如果静态配置文件无意损坏后,会影响openGauss感知openGauss拓扑结构和主备关系。使用gs_om工具生成的静态配置文件,可以替换已经损坏的配置文件,保证openGauss的正常运行。  前置条件 无。  操作步骤 以操作系统用户omm登录数据库主节点。  执行如下命令会在本服务器指定目录下生成配置文件。  "" gs_om -t generateconf -X /opt/software/openGauss/clusterconfig.xml --distribute /opt/software/openGauss/clusterconfig.xml为openGauss安装时的XML配置文件。   说明:  执行命令后,日志信息中会有新文件的存放的目录。以一主两备环境为例,打开新文件存放目录,会出现3个以主机名命名的配置文件,需要用这3个文件分别替换对应主机的配置文件。  若不使用--distribute参数,需执行步骤3将静态配置文件分配到对应节点;若使用--distribute参数,则会将生成的静态配置文件自动分配到对应节点,无需执行步骤3。  (可选)分别替换3台主机的/opt/gaussdb/app/bin目录下损坏的静态配置文件。  这里以其中一台主机为例进行介绍。  "" mv /opt/huawei/wisequery/script/static_config_files/cluster_static_config_SIA1000056771  /opt/gaussdb/app/bin/cluster_static_config 示例 在openGauss中的任意主机上执行如下命令,生成配置文件:  "" gs_om -t generateconf -X  /opt/software/openGauss/clusterconfig.xml --distribute Generating static configuration files for all nodes. Creating temp directory to store static configuration files. Successfully created the temp directory. Generating static configuration files. Successfully generated static configuration files. Static configuration files for all nodes are saved in /opt/huawei/Bigdata/mppdb/wisequery/script/static_config_files. Distributing static configuration files to all nodes. Successfully distributed static configuration files. 打开生成的配置文件目录,会看到新生成的3个文件:  "" cd /opt/huawei/Bigdata/mppdb/wisequery/script/static_config_files ll total 456 -rwxr-xr-x 1 omm dbgrp 155648 2016-07-13 15:51 cluster_static_config_plat1 -rwxr-xr-x 1 omm dbgrp 155648 2016-07-13 15:51 cluster_static_config_plat2 -rwxr-xr-x 1 omm dbgrp 155648 2016-07-13 15:51 cluster_static_config_plat3   
  • [行业资讯] openGauss逻辑备份与恢复
     gs_dump 背景信息 gs_dump是openGauss用于导出数据库相关信息的工具,用户可以自定义导出一个数据库或其中的对象(模式、表、视图等),回收站对象除外。支持导出的数据库可以是默认数据库postgres,也可以是自定义数据库。  gs_dump工具由操作系统用户omm执行。  gs_dump工具在进行数据导出时,其他用户可以访问openGauss数据库(读或写)。  gs_dump工具支持导出完整一致的数据。例如,T1时刻启动gs_dump导出A数据库,那么导出数据结果将会是T1时刻A数据库的数据状态,T1时刻之后对A数据库的修改不会被导出。  gs_dump时生成列不会被转储。  gs_dump支持导出兼容v1版本数据库的文本格式文件。  gs_dump支持将数据库信息导出至纯文本格式的SQL脚本文件或其他归档文件中。  纯文本格式的SQL脚本文件:包含将数据库恢复为其保存时的状态所需的SQL语句。通过gsql运行该SQL脚本文件,可以恢复数据库。即使在其他主机和其他数据库产品上,只要对SQL脚本文件稍作修改,也可以用来重建数据库。 归档格式文件:包含将数据库恢复为其保存时的状态所需的数据,可以是tar格式、目录归档格式或自定义归档格式,详见表1。该导出结果必须与gs_restore配合使用来恢复数据库,gs_restore工具在导入时,系统允许用户选择需要导入的内容,甚至可以在导入之前对等待导入的内容进行排序。 主要功能  gs_dump可以创建四种不同的导出文件格式,通过**[-F或者–format=]**选项指定,具体如表1所示。  表 1 导出文件格式  格式名称  -F的参数值  说明  建议  对应导入工具  纯文本格式  p  纯文本脚本文件包含SQL语句和命令。命令可以由gsql命令行终端程序执行,用于重新创建数据库对象并加载表数据。  小型数据库,一般推荐纯文本格式。  使用gsql工具恢复数据库对象前,可根据需要使用文本编辑器编辑纯文本导出文件。  自定义归档格式  c  一种二进制文件。支持从导出文件中恢复所有或所选数据库对象。  中型或大型数据库,推荐自定义归档格式。  使用gs_restore可以选择要从自定义归档/目录归档/tar归档导出文件中导入相应的数据库对象。  目录归档格式  d  该格式会创建一个目录,该目录包含两类文件,一类是目录文件,另一类是每个表和blob对象对应的数据文件。  -  tar归档格式  t  tar归档文件支持从导出文件中恢复所有或所选数据库对象。tar归档格式不支持压缩且对于单独表大小应小于8GB。  -    说明:  可以使用gs_dump程序将文件压缩为目录归档或自定义归档导出文件,减少导出文件的大小。生成目录归档或自定义归档导出文件时,默认进行中等级别的压缩。gs_dump程序无法压缩已归档导出文件。  注意事项 禁止修改-F c/d/t 格式导出的文件和内容,否则可能无法恢复成功。对于-F p 格式导出的文件,如有需要,可根据需要谨慎编辑导出文件。 为了保证数据一致性和完整性,gs_dump会对需要转储的表设置共享锁。如果表在别的事务中设置了共享锁,gs_dump会等待锁释放后锁定表。如果无法在指定时间内锁定某个表,转储会失败。用户可以通过指定–lock-wait-timeout选项,自定义等待锁超时时间。 不支持加密导出存储过程和函数。 语法 "" gs_dump [OPTION]... [DBNAME]   说明:  “DBNAME"前面不需要加短或长选项。“DBNAME指定要连接的数据库。 例如: 不需要-d,直接指"DBNAME”。  ""   gs_dump -p port_number  postgres -f dump1.sql 或者  ""   export PGDATABASE=postgres  ""   gs_dump -p port_number -f dump1.sql 环境变量: PGDATABASE 
  • [其他] SpringBoot中事务的使用-@Transactional
    事务管理事务管理是应用系统开发中必不可少的一部分。Spring为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式管理事务在有些场景下,我们需要获取事务的状态,是执行成功了还是失败回滚了,那么使用声明式事务就不够用了,需要编程式事务。在SpringBoot中,可以使用两种编程式事务。TransactionManager管理事务TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { for (int i = 0; i < 10; i++) { Post post = new Post(); if (i == 5) { post.setContent("dddddddddddddddddddddddddddddddddddddddddddd"); } else post.setContent("post" + i); post.setWeight(i); postService.save(post); } transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); e.printStackTrace(); }TransactionTemplate借助(TransactionCallback)执行事务管理,带有返回值:public Object getObject(String str) { /* * 执行带有返回值<Object>的事务管理 */ transactionTemplate.execute(new TransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus transactionStatus) { try { ... //....... 业务代码 return new Object(); } catch (Exception e) { //回滚 transactionStatus.setRollbackOnly(); return null; } } }); } 声明式管理事务1、在 spring 项目中,@Transactional注解默认会回滚运行时异常及其子类,这个范围之外的异常 Spring不会帮我们去回滚数据(如果也想要回滚,在方法或者类加上@Transactional(rollbackFor = Exception.class) 即可)。异常继承体系如下图 Throwable 是最顶层的父类,有 Error 和 Exception 两个子类。Error:表示严重的错误(如OOM等)。Exception 可以分为运行时异常(RuntimeException及其子类)和非运行时异常( Exception 的子类中,除了RuntimeException及其子类之外的类)。非运行时异常是检查异常( checked exceptions),一定要try catch,因为这类异常是可预料的,编译阶段就检查的出来。如果不抛出异常,该行代码是会报错的,项目也会启动不起来。Error 和运行时异常是非检查异常( unchecked exceptions ),不需要 try catch,因为这类异常是不可预料的,编译阶段不会检查。@Transactional 注解只能应用到 public 方法或者类上才有效参考: cid:link_1 cid:link_0
  • [其他] 事务的传播机制
    事务的传播机制事务的传播行为就是在两个都启用了事务的方法进行嵌套调用时,外层事务和内层事务的执行动作,Spring支持七种传播方式,他们的效果如下:REQUIRED如果有外层事务,则加入这个事务,否则开启一个新的事务。REQUIRED的效果为外部事务和内部事务同属于一个事务,任何一个回滚都会引起所有事务回滚定义一个没有异常的新增操作和一个有异常的新增操作,分别加上事务,并指定事务传播行为为REQUIREDSUPPORTS如果有外层事务,则加入这个事务,否则就以非事务方式执行 MANDATORY如果有外层事务,则加入这个事务,否则抛出异常 REQUIRES_NEW开启一个独立的新事务执行。REQUIRES_NEW的效果为外部事务和内部事务属于不同事务,内部事务和外部事务都可以单独回滚定义一个没有异常的新增操作和一个有异常的新增操作,分别加上事务,并指定事务传播行为为REQUIRES_NEWNOT_SUPPORTED方法不应该以事务方法执行,如果有外层事务,就以非事务方式执行 NEVER方法不应该以事务方法执行,如果有外层事务,就抛出异常 NESTED开启一个外层事务的子事务执行。NESTED的效果为内部事务为外部事务的子事务,内部事务回滚不会引起外部事务回滚,而外部事务回滚会引起内部事务回滚定义一个没有异常的新增操作和一个有异常的新增操作,分别加上事务,并指定事务传播行为为NESTED形象说明:为了更好的理解,下面形象的说明一下几种传播机制是什么意思:比如你下班回家,有以下几种场景REQUIRED ------ 就是如果老婆做饭了,你就吃老婆做的饭;如果老婆没有做饭,你就自己做饭吃,反正你就是要吃饭(反正要在事务中运行);SUPPORTS ------ 如果老婆做饭了,你就吃老婆做的饭;如果老婆没有做饭,你就不吃(不一定非要在事务中运行);MANDATORY ------ 非要吃老婆做的饭,老婆要是没有做饭,你就大发脾气,典型的家暴男;REQUIRES_NEW ------ 劳资非要吃自己做的饭,就算老婆把饭做好了,你也不吃老婆做的;NOT_SUPPORTED ------ 劳资就是不吃饭,就算老婆把饭做好了,我也不吃;NEVER ------ 劳资就是不吃饭,如果老婆把饭做好了,我还要发脾气;NESTED ------ 暂不做解释;参考:cid:link_1 cid:link_0
总条数:323 到第
上滑加载中