我有一个问题,必须多次回答,但我找不到任何好的搜索词来找出解决问题的最佳方法。
在我的应用程序中,我将拥有不同类型的用户,它们将具有不同的属性和不同的方法,但其中大部分也将是相同的。所以我创建了一个基类'User'和其他类'Player','trainer'等等......继承自'User'类。
我应该如何将这个保存在数据库中,在一个名为“User”的大表中,它具有所有类的所有不同属性,或者我的数据库应该像我的类一样?我认为解决方案2更好。
我只会有一个登录方法,所以它总会返回基类,但是当应该使用不同的特定类型('player','trainer')时,会有一个强制转换为该类。但是我如何进行数据库调用以填充我的不同类。
我能做的是在用户表中也保存了类型。当我将该信息返回到我的代码时,我检查类型是什么,然后调用数据库获取该类型的特定信息,创建正确的类型并将其作为代码中的“用户”返回。但我不喜欢我需要两次调用数据库来用数据填充我的对象的想法,我可以用SP解决它,但我尽量不使用SP。
当我不知道在调用数据库时将返回什么类型时,有没有一种方法可以通过一次调用数据库来解决这个问题。
感谢您的帮助。
答案 0 :(得分:1)
这称为“多态持久性”。有多种方法可以做到这一点。所有这些都有一个共同点,即基表中有一列包含每行中对象的真实类。
OR映射器使用此列加载同一个表的更多列或连接其他表中的列。
请参阅Hibernate docs for more details。这是一个example from Java Tips。
答案 1 :(得分:1)
首先,在我看来,我建议你不要考虑基于面向对象软件解决方案的关系设计。
将最后一句视为真,我的提示将是在业务中有事可做的每种类型的实体,您将为其设计数据表。
无论如何,我发现你可以有另一种关系设计。为什么不创建这样的“用户”表,其中包含基本信息,如唯一标识符,凭据以及用户识别,身份验证和授权所需的任何其他基本信息?
有了这个,你可以设计一个名为“TrainerUsersProfiles”,“PlayerUsersProfiles”等的关系表。
事实上,“TrainerUsersProfiles”,“PlayerUsersProfiles”就像是一个配置文件数据,因为你必须是一个用户才能进行身份验证并获得应用程序资源的授权。但是用户可以拥有更多相关信息,比如说它是“个人资料”。作为培训师或玩家的任何信息都是用户个人资料的一部分。
现在是时候找到在培训师和玩家(以及任何其他人)上共享的属性。此类共享属性应位于用户的配置文件表“UsersProfiles”中,该表与特定用户具有一对一的关系。
例如,我将任何扩展的配置文件数据放在“TrainerUsersProfiles”和“PlayerUsersProfiles”中,并且两者(或更多)与某些用户配置文件具有一对一的关系。
总结:用户拥有个人资料,个人资料具有扩展的专业个人资料数据。
谈到面向对象的层 - 应用程序 - ,我想建议最好避免使用抽象工厂并使用存储库:
userRepository.GetById([id])
用户类将具有“Kind”属性,该属性是用户配置文件种类的集合(培训师,播放器等)。
此外,User类将具有“Profile”属性,该属性本身也应具有“Properties”属性。 “属性”属于类似“ProfileProperties”的类型,并且有一个“TrainerProperties”和“PlayerProperties”派生它。
最后,这将是一些示例用法:
User someUser = userRepository.GetById([id]);
string somePropertyValue = null;
switch(someUser.Kind)
{
case Trainer:
somePropertyValue = ((TrainerProperties)someUser.Profile.Properties).SomeTrainerProperty;
break;
case Player:
somePropertyValue = ((PlayerProperties)someUser.Profile.Properties).SomePlayerProperty;
break;
}
我相信这可能是您正确的解决方案,它可以以良好的关系和面向对象的设计结束。