C++ 具有大量数据的类型安全实体对象
目前,我们的系统使用类似于Java实体bean的东西,尽管它是用C++/SQL编写的。本质上,有些类(或多或少)表示表,这些类的实例相当于表行。我想补充一点,这种方法是有缺陷的,首先,请看这篇著名的文章: 另一方面,它工作得很好,只要你接受它会导致一些不纯的东西,有时会有点黑客 然而,实际问题如下:虽然这些实体中的许多在内存占用方面相对较轻(有十几列包含int、float和string),并产生了良好的性能,但其中一些实体实际上不是C++ 具有大量数据的类型安全实体对象,c++,sql,entity,C++,Sql,Entity,目前,我们的系统使用类似于Java实体bean的东西,尽管它是用C++/SQL编写的。本质上,有些类(或多或少)表示表,这些类的实例相当于表行。我想补充一点,这种方法是有缺陷的,首先,请看这篇著名的文章: 另一方面,它工作得很好,只要你接受它会导致一些不纯的东西,有时会有点黑客 然而,实际问题如下:虽然这些实体中的许多在内存占用方面相对较轻(有十几列包含int、float和string),并产生了良好的性能,但其中一些实体实际上不是 有些包含二进制斑点,如网格或图片。有人可能会争辩说,这些数据一
std::vector< EntityTuple<EmptyPassport, FullPassport>>
std::vector
我得到的所有类型安全性都是以可读性为代价的,这并不是一个很大的改进。目前,我没有更好的想法,怀疑这在C++中是不可能的,但我可能错了。非C++的建议也是受欢迎的,将来可能有更好的方法。当然,如果有人能很好地说明为什么这是不可能的,我也会接受。概述 让我提出一些想法来处理“重”属性,如斑点、图像和文件。请记住,没有“一个解决方案适用于所有人”。我个人反对“装载所有重型财产”的想法,并建议其他想法 在我继续之前,请忽略一些小的语法或逻辑错误,并将重点放在代码示例的逻辑上 [1]定义示例 首先,让我们从一个简单的例子开始:
public class EmployeeClass
{
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo; // <- picture
Blob* Contract; // <- scanned contract
}; // class
许多开发人员只使用“commonlight构造函数”,拒绝使用多个构造函数
[3]其他帮助
让我们暂时跳过“重”属性,稍后将继续
这是许多C/C++开发人员不喜欢的建议,但是,我个人认为在处理实体对象时非常有用。我使用“两步初始化”
对于每个实体类,我声明一个构造函数,没有清除字段的参数,
另外,添加一个虚拟方法,该方法具有一个非常特定的标识符,充当构造函数的角色
然后,我可以添加几个虚拟方法作为构造函数,比如决定是否加载“重”属性
因此,前面的示例变成如下所示:
public class EmployeeClass
{
public:
bool F_EmployeeClass_IsReady;
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo;
Blob* Contract;
public:
// --> only generic constructor
Employee()
{
F_EmployeeClass_IsReady = false;
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
} // EmployeeClass()
virtual bool IsReady()
{
return F_EmployeeClass_IsReady;
} // bool IsReady(...)
// --> works like "generic" constructor from previous example
virtual void Create()
{
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void Create()
// --> works like "light" constructor from previous example
virtual void CreateLight
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void CreateLight()
virtual void Destroy()
{
F_EmployeeClass_IsReady = false;
} // void Destroy()
// --> works like "heavy" constructor from previous example
virtual void CreateHeavy
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
F_EmployeeClass_IsReady = true;
} // void CreateHeavy()
void Insert();
}; // class
void Test()
{
...
int AKey = 0;
char AFirstName[150];
char ALastName[150];
Image* APhoto = null;
Blob* AContract = null;
// --> calling "light" constructor
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->CreateLight(AKey, AFirstName, ALastName);
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
// --> calling "heavy" constructor
AKey = 2;
strcpy(AFirstName, "John");
strcpy(ALastName, "Doe");
Image* APhoto = LoadPhoto();
Blob* AContract = LoadContract();
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->CreateHeavy
(AKey, AFirstName, ALastName, APhoto, AContract);
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
// --> calling "dummy" constructor,
// --> more work, but, more flexible
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->Create();
AEmployee->Key = AKey;
strcpy(AEmployee->FirstName, AFirstName);
strcpy(AEmployee->LastName, ALastName);
AEmployee->Photo = LoadPhoto();
AEmployee->Contract = LoadContract();
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
...
} // void Test()
在前面的示例中,每个实体都是使用两个步骤创建的,“虚拟”构造函数和一个互补方法,每种情况下都不同,并带有一个有意义的标识符,在选择如何准备实体对象时非常有用
每个物体的破坏也是如此
[4]重属性方法
最后,您可能需要添加一些方法,在需要时负责加载“重”属性。有时显式调用,有时自动调用
public class EmployeeClass
{
public:
bool F_EmployeeClass_IsReady;
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo;
Blob* Contract;
public:
// --> only generic constructor
Employee()
{
F_EmployeeClass_IsReady = false;
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
} // EmployeeClass()
virtual bool IsReady()
{
return F_EmployeeClass_IsReady;
} // bool IsReady(...)
void LoadPhoto();
void SavePhoto();
void LoadContract();
void SaveContract();
// --> works like "generic" constructor from previous example
virtual void Create()
{
Key = 0;
strcpy(FirstName, "");
strcpy(LastName, "");
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void Create()
// --> works like "light" constructor from previous example
virtual void CreateLight
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
F_EmployeeClass_IsReady = true;
} // void CreateLight()
virtual void Destroy()
{
F_EmployeeClass_IsReady = false;
} // void Destroy()
// --> works like "heavy" constructor from previous example
virtual void CreateHeavy
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
F_EmployeeClass_IsReady = true;
} // void CreateHeavy()
// --> works like "heavy" constructor from previous example
virtual void CreateAndLoad
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName);
strcpy(LastName, ALastName);
LoadPhoto();
LoadContract;
F_EmployeeClass_IsReady = true;
} // void CreateAndLoad()
void Insert();
}; // class
void Test()
{
...
int AKey = 0;
char AFirstName[150];
char ALastName[150];
Image* APhoto = null;
Blob* AContract = null;
// --> calling "load" constructor
AKey = 1;
strcpy(AFirstName, "Mary");
strcpy(ALastName, "Thompson");
EmployeeClass* AEmployee = new EmployeeClass();
AEmployee->CreateLoad(AKey, AFirstName, ALastName);
AEmployee->Insert();
AEmployee->Destroy();
delete AEmployee;
...
} // void Test()
对于其他方法,您可能有一个忽略它们的[fake]构造函数,而不加载“heavy”属性,一个调用它们的[fake]构造函数。或者,使用不使用它们的[fake]构造函数,显式调用特定“heavy”属性的加载程序
如果您从文件系统路径加载映像并将其保存到数据库字段中,或者从数据库字段加载文件并将其保存到文件系统路径中,这些也会有所帮助
干杯。[编辑]你的“旗帜”想法没问题
在另一个答案中,我提供了另一个解决方案,我个人认为这是一个更好的解决方案,但是,这并不意味着你的想法是错误的
下面的例子,我确实在某些情况下应用过,它是相同的“标志”思想,一个可能的实现,您可能想要或不想要遵循
例如:
public class EmployeeClass
{
// --> logic fields
private:
bool F_HeavyLoaded;
// --> "entity" fields
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo; // <- picture
Blob* Contract; // <- scanned contract
public:
// --> constructors
EmployeeClass
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName;
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
F_HeavyLoaded = false;
} // EmployeeClass()
// --> "heavy" constructor
EmployeeClass
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName;
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
F_HeavyLoaded = true;
} // EmployeeClass()
public:
// --> "entity" methods
bool IsHeavyLoaded() { return F_HeavyLoaded; }
void Insert();
void Update();
void Delete();
}; // class
公共类EmployeeClass
{
//-->逻辑字段
私人:
沉重的布尔夫;
//-->“实体”字段
公众:
int键;
char FirstName[150];
char LastName[150];
图像*照片;/“重”构造器
雇员阶级
(
因塔基,
char*affirstname,
char*ALastName,
图片*阿佛托,
滴状体
)
{
Key=AKey;
strcpy(FirstName,affirstname;
strcpy(LastName,ALastName);
照片=无眼;
合同=合同;
F_HeavyLoaded=真;
}//EmployeeClass()
public class EmployeeClass
{
// --> logic fields
private:
bool F_HeavyLoaded;
// --> "entity" fields
public:
int Key;
char FirstName[150];
char LastName[150];
Image* Photo; // <- picture
Blob* Contract; // <- scanned contract
public:
// --> constructors
EmployeeClass
(
int AKey,
char* AFirstName,
char* ALastName
)
{
Key = AKey;
strcpy(FirstName, AFirstName;
strcpy(LastName, ALastName);
Photo = null;
Contract = null;
F_HeavyLoaded = false;
} // EmployeeClass()
// --> "heavy" constructor
EmployeeClass
(
int AKey,
char* AFirstName,
char* ALastName,
Image* APhoto,
Blob* AContract
)
{
Key = AKey;
strcpy(FirstName, AFirstName;
strcpy(LastName, ALastName);
Photo = APhoto;
Contract = AContract;
F_HeavyLoaded = true;
} // EmployeeClass()
public:
// --> "entity" methods
bool IsHeavyLoaded() { return F_HeavyLoaded; }
void Insert();
void Update();
void Delete();
}; // class