对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去。

在今日的企业环境中,把面向对象软件和关系数据库一起使用可能是相当麻烦和浪费时间的,ORM

 

不仅仅管理.NET类到数据库表的映射(包括.NET 数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和ADO.NET处理数据的时间。

现在有很多成熟的开源框架支持ORM,如:NHibernate,PDO....等 但是他们内部是怎么实现的, 通过一个非常简单的实例让我们一起来探索其中最为关键的过程. (适合ORM初学者)我们以Sql Server 为例

定义操作类型枚举, 为增强可读性 将枚举名使用中文,在实际应用中不建议使用中文作为枚举名称。

  1. public class DataMessageClass
  2. {
  3. public enum DataMessage
  4. {
  5. 数据连接失败,系统忙请等待,操作成功,可继续操作
  6. }
  7. }

标记实体映射基类

  1. /// <summary>
  2. /// DataBase 的摘要说明。
  3. /// </summary>
  4. public interface IDataBase
  5. {
  6. }

自定义属性类,DataObjectAttribute 用于标记映射实体所对应的数据表 FieldObjectAttribute用于标记字段所代表的特殊属性

需要的对数据库表和字段的简单表示我们都有了,下一步来实现对Sql Server 数据表的,Select ,Update,Insert 等操作,ORM映射实现类。

 public class DataAccess
{
private static string mConnectStr=string.Empty;
private static System.Data.SqlClient.SqlConnection mSqlConnect; //连接
private static System.Data.SqlClient.SqlCommand mSqlCmd; // 执行命令
private static System.Data.SqlClient.SqlDataAdapter mDataAdapter; //装配件
private const string mConnectKey="TestConnect"; // 数据库连接字符串键名
public DataAccess()
{
try
{
//
// TODO: 在此处添加构造函数逻辑
//
mConnectStr=GetConnectValue();
mSqlConnect= new SqlConnection(mConnectStr);
mSqlConnect.Open();
}
catch
{
mSqlConnect= new SqlConnection(mConnectStr);
}
}
public void Close()
{
if (mSqlConnect != null && mSqlConnect.State != ConnectionState.Closed)
{
mSqlConnect.Close();
}
}
/// <summary>
/// 初始化数据连接对象
/// </summary>
/// <param name="ConnectStr"></param>
public DataAccess(string ConnectStr)
{
//
// TODO: 在此处添加构造函数逻辑
//
mConnectStr=ConnectStr;
mSqlConnect= new SqlConnection(mConnectStr);
mSqlConnect.Open();
}
/// <summary>
/// 获得连接字符串的值
/// </summary>
/// <returns></returns>
private string GetConnectValue()
{
return System.Configuration.ConfigurationSettings.AppSettings[mConnectKey].ToString();
}
private DataMessageClass.DataMessage CheckOpenState()
{
if(mSqlConnect.State==System.Data.ConnectionState.Broken || mSqlConnect.State==System.Data.ConnectionState.Closed)
{
mSqlConnect.Close();
mSqlConnect.ConnectionString = mConnectStr;
try
{
lock(mSqlConnect)
{
mSqlConnect.Open();
}
}
catch(System.Exception ex)
{
return DataMessageClass.DataMessage.数据连接失败;
}
}
if(mSqlConnect.State==System.Data.ConnectionState.Executing || mSqlConnect.State==System.Data.ConnectionState.Fetching || mSqlConnect.State==System.Data.ConnectionState.Connecting)
{
return DataMessageClass.DataMessage.系统忙请等待;
}
return DataMessageClass.DataMessage.可继续操作;
}
/// <summary>
/// 执行Sql语句 带参数
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <param name="ExeSqlParameter">参数</param>
/// <returns></returns>
public DataMessageClass.DataMessage ExeSQL(string ExeSqlStr,System.Data.SqlClient.SqlParameter[] ExeSqlParameter)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in ExeSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);}
}
mSqlCmd.ExecuteNonQuery();
}
return DataMessageClass.DataMessage.操作成功;
}
/// <summary>
/// 执行Sql语句 不带参数
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <returns></returns>
public DataMessageClass.DataMessage ExeSQL(string ExeSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
mSqlCmd.ExecuteNonQuery();
}
return DataMessageClass.DataMessage.操作成功;
}
/// <summary>
/// 执行Sql语句 不带参数 返回一个值
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <returns></returns>
public object ExeSQLReturnValue(string ExeSqlStr,System.Data.SqlClient.SqlParameter[] ExeSqlParameter)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in ExeSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);};
}
return mSqlCmd.ExecuteScalar();
}
return null;
}
/// <summary>
/// 执行Sql语句 不带参数 返回一个值
/// </summary>
/// <param name="ExeSqlStr">语句</param>
/// <returns></returns>
public object ExeSQLReturnValue(string ExeSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(ExeSqlStr,mSqlConnect);
return mSqlCmd.ExecuteScalar();
}
return null;
}
/// <summary>
/// 获得查询表记录 带参数
/// </summary>
/// <param name="SelSqlStr">语句</param>
/// <param name="SelSqlParameter">参数</param>
/// <returns>数据集合</returns>
public System.Data.DataSet GetSelectRow(string SelSqlStr,System.Data.SqlClient.SqlParameter[] SelSqlParameter)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SelSqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in SelSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);};
}
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet);
return TempDataSet;
}
return null;
}
/// <summary>
/// 获得查询表记录 不带参数
/// </summary>
/// <param name="SelSqlStr">语句</param>
/// <returns>set数据集合</returns>
public System.Data.DataSet GetSelectRow(string SelSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SelSqlStr,mSqlConnect);
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet);
return TempDataSet;
}
return null;
}
/// <summary>
/// 获得查询表记录 不带参数
/// </summary>
/// <param name="SelSqlStr">语句</param>
/// <returns>Reader数据集合</returns>
public System.Data.SqlClient.SqlDataReader GetSelectRowReader(string SelSqlStr)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SelSqlStr,mSqlConnect);
// 装入数据
System.Data.SqlClient.SqlDataReader TDataReader;
TDataReader=mSqlCmd.ExecuteReader();
return TDataReader;
}
return null;
}
/// <summary>
/// 分页读取
/// </summary>
/// <param name="SqlStr">语句</param>
/// <param name="SelSqlParameter">参数</param>
/// <param name="DataSetName">名称</param>
/// <param name="PageIndex">当前页面</param>
/// <param name="MaxReocrd">记录数</param>
/// <returns></returns>
public System.Data.DataSet GetPageDataSet(string SqlStr,System.Data.SqlClient.SqlParameter[] SelSqlParameter,string DataSetName,int PageIndex,int MaxReocrd)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SqlStr,mSqlConnect);
foreach(System.Data.SqlClient.SqlParameter tParameter in SelSqlParameter)
{
if(tParameter!=null){mSqlCmd.Parameters.Add(tParameter);};
}
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet,(PageIndex-) * MaxReocrd, MaxReocrd,DataSetName);
return TempDataSet;
}
return null;
}
/// <summary>
/// 分页读取 不带参数
/// </summary>
/// <param name="SqlStr">语句</param>
/// <param name="SelSqlParameter">参数</param>
/// <param name="DataSetName">名称</param>
/// <param name="PageIndex">当前页面</param>
/// <param name="MaxReocrd">记录数</param>
/// <returns></returns>
public System.Data.DataSet GetPageDataSet(string SqlStr,string DataSetName,int PageIndex,int MaxReocrd)
{
DataMessageClass.DataMessage tDataMessage;
tDataMessage=CheckOpenState();
if (tDataMessage==DataMessageClass.DataMessage.可继续操作)
{
mSqlCmd=new SqlCommand(SqlStr,mSqlConnect);
// 装入数据
System.Data.DataSet TempDataSet = new DataSet();
mDataAdapter=new SqlDataAdapter(mSqlCmd);
mDataAdapter.Fill(TempDataSet,(PageIndex-) * MaxReocrd, MaxReocrd,DataSetName);
return TempDataSet;
}
return null;
}
/// <summary>
/// 获得一个对象
/// </summary>
/// <param name="TDataBase"></param>
public IDataBase GetOnlyObject(IDataBase TDataBase)
{
// 生成条件
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[KeyS.Length];
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
string SelSql="Select * From " + TableName + " ";
for (byte index=; index<KeyS.Length;index++)
{
if (index==)
SelSql += " Where " + KeyS[index] + " = @" + KeyS[index] + " " ;
else
SelSql += " and " + KeyS[index] + " = @" + KeyS[index] + " " ;
TSqlParameter[index]=new SqlParameter("@" + KeyS[index] ,TDataBase.GetType().GetField(KeyS[index]).GetValue(TDataBase));
}
// 得到记录
System.Data.DataSet TDataSet= new DataSet();
TDataSet=GetSelectRow(SelSql,TSqlParameter);
if (TDataSet.Tables[].Rows.Count ==) {return null;}
// 把数据分配到字段
foreach (System.Reflection.FieldInfo TFieldInfo in mFieldInfo)
{
TDataBase.GetType().GetField(TFieldInfo.Name).SetValue(TDataBase,TDataSet.Tables[].Rows[][TFieldInfo.Name]==System.DBNull.Value ? GetTypeValue(TFieldInfo.FieldType) :TDataSet.Tables[].Rows[][TFieldInfo.Name]);
}
return TDataBase;
}
/// <summary>
/// 得到初始值
/// </summary>
/// <param name="TType"></param>
/// <returns></returns>
private object GetTypeValue(System.Type TType)
{
if(TType.FullName.Equals(System.TypeCode.DateTime.GetType()))
{
return System.DateTime.Now;
}
return null;
}
/// <summary>
/// 添加一个对象
/// </summary>
/// <param name="TDataBase"></param>
public object AddOnlyObjectReturnIndex(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[mFieldInfo.Length];
string SelSql="insert into " + TableName + " ";
string FieldName =string.Empty;
string ValueName =string.Empty;
for (byte index= ; index <mFieldInfo.Length ; index ++)
{
if(mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false).Length!=)
{
FieldObjectAttribute TFieldObject =mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false)[] as FieldObjectAttribute;
if (TFieldObject.Type==)
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,System.Guid.NewGuid().ToString());
}
else if (TFieldObject.Type==)
{
// 此字段为自增列放弃
}
}
else
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
SelSql += " (" + FieldName + ") VALUES (" + ValueName + ") SELECT @@IDENTITY AS 'Identity'";
return ExeSQLReturnValue(SelSql,TSqlParameter);
}
/// <summary>
/// 添加一个对象
/// </summary>
/// <param name="TDataBase"></param>
public void AddOnlyObject(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[mFieldInfo.Length];
string SelSql="insert into " + TableName + " ";
string FieldName =string.Empty;
string ValueName =string.Empty;
for (byte index= ; index <mFieldInfo.Length ; index ++)
{
if(mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false).Length!=)
{
FieldObjectAttribute TFieldObject =mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false)[] as FieldObjectAttribute;
if (TFieldObject.Type==)
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,System.Guid.NewGuid().ToString());
}
else if (TFieldObject.Type==)
{
// 此字段为自增列放弃
}
}
else
{
FieldName += FieldName.Length > ? "," + mFieldInfo[index].Name : mFieldInfo[index].Name ;
ValueName += ValueName.Length > ? "," + "@" + mFieldInfo[index].Name : "@" + mFieldInfo[index].Name ;
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
SelSql += " (" + FieldName + ") VALUES (" + ValueName + ")";
ExeSQL(SelSql,TSqlParameter);
}
/// <summary>
/// 更新一个对象
/// </summary>
/// <param name="TDataBase"></param>
public void UpdateOnlyObject(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
Array TArray = Array.CreateInstance(typeof(string),KeyS.Length);
KeyS.CopyTo(TArray,);
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[mFieldInfo.Length];
string SelSql="Update " + TableName + " Set ";
string FieldValueName =string.Empty;
string WhereName = string.Empty;
for (byte index= ; index <mFieldInfo.Length ; index ++)
{
if(mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false).Length!=)
{
FieldObjectAttribute TFieldObject =mFieldInfo[index].GetCustomAttributes(typeof(FieldObjectAttribute),false)[] as FieldObjectAttribute;
if (TFieldObject.Type==)
{
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
else
{
if(Array.IndexOf(TArray,mFieldInfo[index].Name)==-)
{
FieldValueName += FieldValueName.Length > ? ", " + mFieldInfo[index].Name + "=@" + mFieldInfo[index].Name : mFieldInfo[index].Name + "=@" + mFieldInfo[index].Name;
}
TSqlParameter[index]=new SqlParameter("@" + mFieldInfo[index].Name ,TDataBase.GetType().GetField(mFieldInfo[index].Name).GetValue(TDataBase));
}
}
for (byte index=; index<KeyS.Length;index++)
{
WhereName += WhereName.Length> ? " and " + KeyS[index] + " = @" + KeyS[index] :" Where " + KeyS[index] + " = @" + KeyS[index] ;
}
SelSql += FieldValueName + WhereName;
ExeSQL(SelSql,TSqlParameter);
}
/// <summary>
/// 删除一个对象
/// </summary>
/// <param name="TDataBase"></param>
public void DelOnlyObject(IDataBase TDataBase)
{
DataObjectAttribute TDataObject =TDataBase.GetType().GetCustomAttributes(typeof(DataObjectAttribute),false)[] as DataObjectAttribute;
string[] KeyS= TDataObject.KeyS.Split(new char[]{','});
string TableName =TDataObject.Table;
System.Reflection.FieldInfo[] mFieldInfo=TDataBase.GetType().GetFields();
System.Data.SqlClient.SqlParameter[] TSqlParameter=new SqlParameter[KeyS.Length];
string SelSql="delete " + TableName ;
string FieldValueName =string.Empty;
for (byte index=; index<KeyS.Length;index++)
{
FieldValueName += FieldValueName.Length> ? " and " + KeyS[index] + " = @" + KeyS[index] :" Where " + KeyS[index] + " = @" + KeyS[index] ;
TSqlParameter[index]=new SqlParameter("@" + KeyS[index] ,TDataBase.GetType().GetField(KeyS[index]).GetValue(TDataBase));
}
SelSql+=FieldValueName;
ExeSQL(SelSql,TSqlParameter);
}
}
 

实现就这么简单了,让我们测试其使用过程。

第一步:定义数据映射实体

 /// <summary>
/// "UserInfo" 标示目标表名
/// "Guid" 代表主键, 可以通过逗号分隔来指定多个主键
/// </summary>
[DataAccess.DataObject("UserInfo", "Guid")]
public class UserInfo : IDataBase
{
/// <summary>
/// FieldObject(0) 标示GUID 类型的主键,FieldObject(1) 标示自增性主键
/// </summary>
[FieldObject()]
public string Guid = string.Empty;
public string UserName = string.Empty;
public string UserEMail = string.Empty;
public string UserTel = string.Empty;
public string UserSex = string.Empty;
public string UserDec = string.Empty;
public string RegIpAddres = string.Empty;
}

第二步:配置连接字符串

 <appSettings>
<add key ="ORMConnect" value ="Data Source=???.??.??.???,1433;Initial Catalog=?????;Persist Security Info=True;User ID=?????;Password=??????"/>
</appSettings >

第三步:测试对数据表的操作

 [c-sharp] view plaincopyprint?

 DataAccess.DataAccess ormAccess= new DataAccess.DataAccess();

 UserInfo info = new UserInfo();
info.UserName = "TestUser" ; info.UserDec = http://www.apace.com.cn; info.UserEMail = G_Jack@.com;
info.UserTel = "";
info.RegIpAddres = “testip”; //测试新增 ormAccess.AddOnlyObject(info); //测试更新 ormAccess.UpdateOnlyObject(info) //测试删除 ormAccess.DelOnlyObject(info)

对ORM的简单实现就到处结束了,希望能帮到大家

C# ORM简单原理的更多相关文章

  1. java中异常处理机制的简单原理

    以上是自认为的java异常处理的简单原理,如有不妥之处还请各位大神帮忙指点,谢谢!

  2. java——关于异常处理机制的简单原理和应用

    异常处理机制的简单原理和应用 一.Execption可以分为java标准定义的异常和程序员自定义异常2种 (1)一种是当程序违反了java语规则的时候,JAVA虚拟机就会将发生的错误表示为一个异常.这 ...

  3. javascript AJAX简单原理及什么是ajax

    AJAX简单原理供初学者理解 AJAX的原理: Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面.这其 ...

  4. ORM实现原理

    1.什么是ORM ORM的全称是Object Relational Mapping,即对象关系映射.它的实现思想就是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的 ...

  5. js编译器的一些简单原理

    有没有发现在写代码的时候,往往会遇到一些莫名其妙的错误,然后时间紧急不得不去网上查阅一些代码.虽然要实现的功能解决了,但是看被拷贝的代码好多真心看不懂,以后遇到诸如此类的问题,如果查阅不到这些代码的话 ...

  6. 为初学者写ORM,ORM的原理及测试案例

    提纲 一.什么是ORM.二.反射以及Attribute在ORM中的应用.三.创建一个数据库表和表对应的实体model.四.实体model如何映射出数据库表.五.组合ORM映射生成insert语句.六. ...

  7. Spring MVC简单原理

    Spring MVC原理 针对有Java Web基础.Spring基础和Spring MVC使用经验者. 前言 目前基于Java的web后端,Spring生态应该是比较常见了.虽然现在流行前后端分离, ...

  8. Android开发学习之路--RxAndroid之简单原理

      学习了RxAndroid,其实也就是RxJava了,但是还是不是非常清楚到底RxAndroid有什么用呢?为什么要使用RxAndroid呢?这篇文章讲得不错,RxJava的原理.但是这里还是把整个 ...

  9. go 利用orm简单实现接口分布式锁

    在开发中有些敏感接口,例如用户余额提现接口,需要考虑在并发情况下接口是否会发生问题.如果用户将自己的多条提现请求同时发送到服务器,代码能否扛得住呢?一旦没做锁,那么就真的会给用户多次提现,给公司带来损 ...

随机推荐

  1. Codility---FrogJmp

    Task description A small frog wants to get to the other side of the road. The frog is currently loca ...

  2. IO多路复用与异步非阻塞

    1.基于socket,发送http请求 import socket import requests # 方式一 list=['li','gh ','nn'] for i in list: ret=re ...

  3. Django预备知识

    http协议 url: 协议://域名(IP)+端口(80)/路径?参数(a=1&b=2) 示例:https://www.baidu.com/s/?wd=aaa MVC M:mdoel 与数据 ...

  4. hadoop之hive集合数据类型

    除了string,boolean,date等基本数据类型之外,hive还支持三种高级数据类型: 1.ARRAY ARRAY类型是由一系列相同数据类型的元素组成,这些元素可以通过下标来访问.比如有一个A ...

  5. 原生js封装轮播图

    个人实际开发中用到的效果问题总结出来便于自己以后开发查看调用,如果也适用其他人请随意拿走勿喷就行! 原生js对于思路要求比较高,在js代码我都写有备注,足够理解并使用,即使是小白或者刚入行的程序员也比 ...

  6. Vim入门操作整理

    根据小甲鱼的vim入门视频整理,供查阅 移动指令:上下左右 k j h l 翻页: ctrl + b  ctrl + f 保存退出:ZZ 普通模式:vim fileName 首次进入的就是普通模式 从 ...

  7. 全自动Landsat影像温度反演软件开发

    许久没有更新遥感类软件开发了,都有点生疏了,这一次我带来了一个老的算法,新的东西, 为什么这么说呢,我们知道Landat8.Landsat5等影像,单个影像去做温度反演,并没有什么太大的难度, 但是呢 ...

  8. 【Netty整理03-NIO】Java 实现 NIO demo

    jdk提供的NIO使用: 概览:https://blog.csdn.net/the_fool_/article/details/83000648 博主抄写了网上的demo,略作修改与调整,原文链接: ...

  9. Java进阶——高性能MySQL(一)

    MySQL逻辑架构: 链接管理与安全性: MySQL5.5或更高版本版本提供了一个API,支持线程池(Thread-Pooling)插件,可以使用池中的少量线程来服务大量的连接. 优化与并行: MyS ...

  10. 【Flink】深入理解Flink-On-Yarn模式

    1. 前言 Flink提供了两种在yarn上运行的模式,分别为Session-Cluster和Per-Job-Cluster模式,本文分析两种模式及启动流程. 下图展示了Flink-On-Yarn模式 ...