Python中的多态性与数据库加载

2024-10-03 19:22:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我在以多态方式将记录加载到数据库时遇到问题。在

我有:

  • 由不同类型的记录(RecordARecordB)扩展的Record对象
  • 一种方法load_record(),它不知道它正在加载什么类型的记录
  • 一个数据库接口,它需要包含关于数据库的所有信息

据我所知,在多态性方面我可以做到:

class RecordA(Record):
    def load_into_db(self, db_impl):
        db_impl.load_record_a(self)


class DbImpl(DbInt):
    def load_record_a(self, record):
        ... 
    def load_record_b(self, record):
        ... 

def load_record(record):
    record.load_into_db(db_impl)

或者

^{pr2}$

这两个看起来都有点笨重。或者,我们可以有效地使用switch语句:

class DbImpl(DbInt):
    procs = { RecordA: ..., RecordB: ...}
    ...

def load_record(record):
    data = record.get_data()
    db_proc = procs[type(record)]
    db_impl.load_record(record_data, db_proc)

现在可能已经很明显了,问题是数据库需要使用特定的存储过程(它在自己的代码中有),但是如果不询问记录本身,它就不知道该使用哪个存储过程。在

例1在我看来是最具多态性的,但它仍然需要在每次添加新记录类型时编辑DbImpl代码,所以它比示例3更好吗?如果是,为什么?在

干杯, 威尔


Tags: self数据库类型dbdatadef记录load
3条回答

在这种情况下,如果记录类型与特定的存储过程相关,那么我会说记录本身需要了解需要运行什么存储过程,并将该数据传递给实现它的DB类。因此,不需要用每个新的记录类型修改DB类。recordType只需要进行编码,以理解需要使用的存储过程名称,并将该名称公开给DB类。在

对我来说最有意义的是拥有一个基类,它包含基本的数据库功能,例如将一些东西放入数据库和连接信息中。然后,从这个基类中,您将对RecordA、RecordB、RecordC、。。。它将保存信息/功能,例如存储过程信息。拥有一个基类,包含大量方法,这感觉很笨拙,在我看来不适合OOP范式。

因此,具有基本数据库功能的基类,那么每个记录子类都将包含该特定记录类型所需的信息。

我也遇到过同样的问题,发现现有的数据库orm缺乏多态性/OOP,为此,我一直在研究一个新的orm,主要集中在这方面。它叫做ORB,可以在:http://docs.projexsoftware.com/api/orb/

现在它只适用于PostgreSQL和Mongo,但是我很快会把它扩展到更多的后端。在

它非常灵活,取决于您要做什么,是否简单,例如:

  • 基类(数据库层)
  • 子类(纯python调用-同一表运行的so控制器逻辑)

或者

  • 基类(抽象层-公共控制器逻辑,未定义表)
  • 子类(数据库层-每个子类定义不同的数据库表)

或者

  • 基类(数据库层-定义根表)
  • 子类(数据库层-为支持它的数据库定义继承的表,为不支持的数据库定义重复的列表)

下面是一个例子:

# import the orb system
from orb import Table, Column, ColumnType, Orb

# define the base class (will create default_fruit table)
class Fruit(Table):
    __db_columns__ = [
        Column(ColumnType.String, 'shape'),
        Column(ColumnType.String, 'color'),
        Column(ColumnType.String, 'name'),
        Column(ColumnType.String, 'classType')
    ]

    def initRecord( self ):
        """
        Set the initialization information from the base Table type
        """
        super(Fruit, self).initRecord()
        self.setRecordDefault('classType', self.__class__.__name__)

    @staticmethod
    def expanded( records ):
        """
        Expands the records based on their class type.

        :return   [<Table>, ..]
        """
        out = []
        for record in records:
            # map the record to their base classes
            model = Orb.instance().model(record.classType())
            if ( not model ):
                out.append(record)
                continue

            expanded_record = model(record)
            if ( not expanded_record.isRecord() ):
                continue

            out.append(expanded_record)
        return out        

# define the sub class (no database table)
class Apple(Fruit):
    def initRecord( self ):
        super(Apple, self).initRecord()
        self.setRecordDefault('shape', 'round')
        self.setRecordDefault('color', 'red')

# define the sub class (with a sub-table, will create default_banana table)
class Banana(Fruit):
    __db_columns__ = [
        Column(ColumnType.String, 'isPlantain')
    ]

    def initRecord( self ):
        super(Banana, self).initRecord()
        self.setRecordDefault('shape', 'oblong')
        self.setRecordDefault('color', 'yellow')

这将定义3个不同的类(Fruit、Apple、Banana)和2个数据库表(default_Fruit,default_Banana)

使用此系统(您必须创建文档中定义的数据库连接等)将给您提供以下内容:

^{pr2}$

相关问题 更多 >