当前位置: 首页 > news >正文

重构数据访问层-优化数据访问的开发

        重新整理了一下过去开发的框架,在准备开发新项目时候,重新整理了一下思路,感觉数据访问层还是很鸡肋。过去几年中,急于完成项目开发和交付,框架都是迭代过来的,虽然满足了开发需求,但是,从安全性、复杂度等方面看,还是有不足的。

        从安全性角度看,查询参数和提交数据的安全校验必须增加。虽然已经使用了对象化参数传递查询参数,防止了SQL注入的情况,但是,数据合法性校验依然没有深度去实现。从过去的实践中发现,前端输入数据的随意性,例如应该是整数,用户输入了字母,但是前端没有做严格的数据限制,或者,前端就是模板生成的代码,校验不严谨,导致系统保存数据的时候,会直接报错。虽然底层对这些报错的情况做了拦截和记录日志,但是严重影响了系统性能。

        复杂度主要是指框架迭代过程中的一些冗余代码。数据访问层的设计,是基于通用性和框架性两个大方面来考虑的。通用性就是不限定映射实体的具体类型和格式,相当于兼容常规的系统开发。但是,从框架角度,特别是业务层面,这些通用的映射实体是很难满足系统框架需求的。因此在这个基础上,增加基于框架设计要求的实体基类,例如包含:

string recordId         数据行的唯一记录,通过uuid(guid)生成字符串

DateTime createDate        记录的创建时间,不允许修改

DateTime updateDate        记录最后修改时间

string createBy                记录创建人ID,这里是员工的编号,不允许修改

string updateBy                记录最后修改人的ID

bool deleted                        记录软删除标记,true表示记录被删除

还有其他一些字段的定义,就不一一列举。

        系统开发离不开与数据库的交互,框架设计初衷就是最大化简化数据交互的方法,降低开发的随意性和复杂性。

        一般来说,系统开发尽量不要直接使用数据库脚本进行数据交互。dotnet中,有丰富的orm可以选择使用,例如ef,dapper,sqlsugar,freesql等等,但是,学习这些组件,也需要花费不少时间,这是其一。其二就是程序员可能直接操作组件,进行任意性的数据操作。从数据库优化角度看,尽量单表查询,减少join表查询,然后程序员有时候为了方便,直接就来join,甚至是好几个表join,也没有注意锁的应用,在数据增加到一定程序,就出现死锁情况。

        orm提供了丰富的lambda方法进行查询,也避免了写错字段的情况。框架把insert\update\delete\get\getlist\getpagelist等方法进行了封装,可以减少95%以上的操作orm的机会,通过封装一层,屏蔽掉了orm的使用,也降低了程序员的学习难度。

        这次重构数据访问层,主要从以下几点考虑:

        一、兼容读写分离。这里两个概念,一个是,有些业务需求,数据是只能读的,例如第三方同步过来的数据。框架增加了Read/Write两层数据访问层,出现只能读的数据,则继承只读的基类即可;二个是主从数据库的读写分离,业务流程的功能代码,使用写的数据库,分析用的数据,使用读的数据库。前段时间自己开发了一个同步软件,把sqlserver数据同步到了clickhouse,读写分离不限制数据库的类型,有利于按需求选择数据库和优化系统开发。

        二、提升分布式事务的安全性。防止某个微服务宕机导致请求等待的情况,例如某个微服务已经接受了分布式事务,但是,突然就宕机了,无法接收提交事务的请求或者回滚事务的请求,导致数据的一致性被破坏。

        三、业务表单支持多个从表的通用访问。在面向对象中,不确定的数据访问层,无法赋予对应的泛型来确定对象,如果使用没有泛型的数据访问对象,根本无法使用lambda进行查询,因此,把数据访问层的接口,拆分成三组,一组是没有泛型的,一组是带实体泛型的,一组是使用逆变泛型的。这样,无论在什么情况下,都可以使用一个统配实体接口,来描述数据访问对象。

        四、更换目前的orm,过去使用ef、chloe,但是使用过程中,存在各种问题,比较了几个orm,选择freesql,比常规的orm支持更多的数据库类型,特别是clickhouse.但是替换难度有点大,尽量轻量化,为不同的数据库要建立不同的接口或者组件,按需动态加载,这里和注入有点不一样,只是用于解析不同数据或者交互的,从开发层面上看,这一层应该是透明的。

        五、强化正则表达式的提交前的数据校验。除了可以在实体属性上定义规则外,还允许在数据访问层添加或者制定验证规则。例如字段的长度、合法内容等,在不同的业务中,可能相同的字段会存在不同的校验规则。

        以下是重新设计后的数据访问层结构图。框架设计把数据归为3类

        1、基础数据,例如员工信息、部门信息这类的

        2、配置数据,流入多对多的关联表

        3、表单数据,例如采购、销售等业务单据

        

相关文章:

重构数据访问层-优化数据访问的开发

重新整理了一下过去开发的框架,在准备开发新项目时候,重新整理了一下思路,感觉数据访问层还是很鸡肋。过去几年中,急于完成项目开发和交付,框架都是迭代过来的,虽然满足了开发需求,但是&#xf…...

云计算概述报告

以下是一篇论述类文章 文章目录 I. 云计算介绍(1)云计算基本概念(2)云计算基本特征 II. 云计算发展历程(1)云计算的起源(2)云计算的发展阶段 III. 云计算特点(1&#xff…...

C++:线程库的使用

文章目录 Windows和Linux平台的线程线程构造函数模板参数包 最近发现C11的线程库还没有进行总结,因此本篇对于C11当中新增的线程库的一些基本用法进行总结 Windows和Linux平台的线程 在Linux平台下是存在一些原生的线程系统调用的,比如有pthread_creat…...

机器学习模型:决策树笔记

第一章:决策树原理 1-决策树算法概述_哔哩哔哩_bilibili 根节点的选择应该用哪个特征?接下来选什么?如何切分? 决策树判断顺序比较重要。可以使用信息增益、信息增益率、 在划分数据集前后信息发生的变化称为信息增益&#xff0c…...

20.2k stars项目搭建私人网盘界面美功能全

Nextcloud是一套用于创建网络硬盘的客户端-服务器软件。其功能与Dropbox相近,但Nextcloud是自由及开放源代码软件,每个人都可以在私人服务器上安装并执行它。 GitHub数据 20.2k stars561 watching3.2k forks 开源地址:https://github.com/ne…...

卷积篇 | YOLOv8改进之引入全维度动态卷积ODConv | 即插即用

前言:Hello大家好,我是小哥谈。ODConv是一种关注了空域、输入通道、输出通道等维度上的动态性的卷积方法,一定程度上讲,ODConv可以视作CondConv的延续,将CondConv中一个维度上的动态特性进行了扩展,同时了考虑了空域、输入通道、输出通道等维度上的动态性,故称之为全维度…...

Pytorch实用教程:torch.from_numpy(X_train)和torch.from_numpy(X_train).float()的区别

在PyTorch中,torch.from_numpy()函数和.float()方法被用来从NumPy数组创建张量,并可能改变张量的数据类型。两者之间的区别主要体现在数据类型的转换上: torch.from_numpy(X_train):这行代码将NumPy数组X_train转换为一个PyTorch张…...

深度学习pytorch好用网站分享

深度学习在线实验室Featurizehttps://featurize.cn/而且这个网站里面还有一些学习教程 免费好用 如何使用 PyTorch 进行图像分类https://featurize.cn/notebooks/5a36fa40-490e-4664-bf98-aa5ad7b2fc2f...

C语言 | Leetcode C语言题解之第2题两数相加

题目: 题解: struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {struct ListNode *head NULL, *tail NULL;int carry 0;while (l1 || l2) {int n1 l1 ? l1->val : 0;int n2 l2 ? l2->val : 0;int sum n1 n2 …...

Oracle基础

Oracle基础 Oracle,作为全球最大的数据库软件供应商,其数据库产品在企业级应用市场中占据了举足轻重的地位。Oracle数据库以高性能、高可用性、高安全性以及强大的数据管理能力赢得了广泛认可。本文旨在为读者提供Oracle数据库的基础知识,帮…...

从0到1实现RPC | 04 负载均衡和静态注册中心

一、Router的定义 Router路由用于预筛选,Dubbo有这样的设计,SpringCloud没有。 二、LoadBanlancer定义 负载均衡器:默认取第一个 当前支持随机和轮询两种负载均衡器。 随机:从所有provider中随机选择一个。 轮询:每…...

卷积神经网络-池化层

卷积神经网络-池化层 池化层(Pooling Layer)是深度学习神经网络中的一个重要组成部分,通常用于减少特征图的空间尺寸,从而降低模型复杂度和计算量,同时还能增强模型的不变性和鲁棒性。 池化操作通常在卷积神经网络&am…...

【干货集】C# XmlHelper帮助类操作Xml文档的通用方法汇总

前言 该篇文章主要总结的是自己平时工作中使用频率比较高的Xml文档操作的一些常用方法和收集网上写的比较好的一些通用Xml文档操作的方法(主要包括Xml序列化和反序列化,Xml文件读取,Xml文档节点内容增删改的一些通过方法)。当然可…...

Coursera自然语言处理专项课程04:Natural Language Processing with Attention Models笔记 Week01

Natural Language Processing with Attention Models Course Certificate 本文是学习这门课 Natural Language Processing with Attention Models的学习笔记,如有侵权,请联系删除。 文章目录 Natural Language Processing with Attention ModelsWeek 01…...

mysql MHA高可用

目录 工作原理 Node(节点) Manager(管理器) Node和Manager的协作 故障转移流程 优势 配置和管理 配置主从复制 MHA实现高可用 MySQL Master High Availability(MHA)是一个开源的高可用性解决方案&…...

android 扫描二维码

1.在你的build.gradle文件中添加Mobile Vision库的依赖: dependencies {implementation com.google.android.gms:play-services-vision:20.1.0 } 2.创建一个新的Activity来处理扫描过程。 import android.Manifest; import android.content.pm.PackageManager; i…...

[flink 实时流基础] 输出算子(Sink)

学习笔记 Flink作为数据处理框架,最终还是要把计算处理的结果写入外部存储,为外部应用提供支持。 文章目录 **连接到外部系统****输出到文件**输出到 Kafka输出到 mysql自定义 sink 连接到外部系统 Flink的DataStream API专门提供了向外部写入数据的方…...

case语句

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 CASE 语句的执行方式与 IF...THEN...ELSIF 语句的执行方式类似,但是它是通过一个表达式的值来决定执行哪个分支 CASE 选择器表达式 WHEN 条件 1 THEN 语句序列 …...

全国加油站分布数据/停车场分布/公园分布/景区分布/保护区分布/poi感兴趣点

加油站是指为汽车和其它机动车辆服务的、零售汽油和机油的补充站,一般为添加燃料油、润滑油等。由于加油站所销售的石油商品具有易燃爆、易挥发、易渗漏、易集聚静电荷的特性,故加油站以“安全”为第一准则。在加油站内严禁烟火,严禁从事可能…...

单片机简介(一)

51单片机 一台能够运行的计算机需要CPU做运算和控制,RAM做数据存储,ROM做程序存储,还有输入/输出设备(串行口、并行输出口等),这些被分为若干块芯片,安装在主板(印刷线路板&#xf…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

git: early EOF

macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

TCP/IP 网络编程 | 服务端 客户端的封装

设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...

电脑桌面太单调,用Python写一个桌面小宠物应用。

下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划,涵盖存储系统的布局、数据存储策略等,它明确数据如何存储、管理与访问,为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...