Tuesday 8 December 2020

SqlAlchemy - Classic Mapping Inheritance - Instance has Null Identity

I'm seeing a NULL Identity key error when trying to write out an object mapped to a table that inherits another one. I've found this example works fine when using the Declarative approach, but not when using the Classical one.

The tables are set up as follows:

objecttypes = Table('objecttypes', metadata,
                    Column('id', Integer, primary_key=True),
                    Column('name', String)
                    )
things = Table('things', metadata,
               Column('id', Integer, primary_key=True, autoincrement=True),
               Column('name', String),
               Column('object_type_id', Integer, ForeignKey('objecttypes.id')),
               Column('version', Integer),
               Column('timeCreated', DateTime)
               )
locations = Table('locations', metadata,
                  Column('id', Integer, ForeignKey('things.id'), primary_key=True))

objecttypes = Table('objecttypes', metadata,
                    Column('id', Integer, primary_key=True),
                    Column('name', String)
                    )
mapper(Thing, things, version_id_col=things.c.version,
       polymorphic_on="object_type_id",
       with_polymorphic='*',
       polymorphic_load='inline',
       properties={
           'objectType': relationship(ObjectType, cascade_backrefs=False)
       })
mapper(Location, locations, polymorphic_identity=typeDict['location'].id)

The classes are set up as:

class ObjectType(object):
    def __repr__(self):
        return "ObjectType({}, id={})".format(self.name, self.id)

class Thing(object):
    def __init__(self, **kwds):
        for key in kwds:
            setattr(self, key, kwds[key])
        return

    def __repr__(self):
        return "{}, id={}, type={}, version={}".format(self.name, self.id, self.objectType, self.version)

class Location(Thing):
    pass

I get the error when I try creating and merging a new Location:

def write(obj):
    session = scopedSessionFactory()
    obj = session.merge(obj)
    session.commit()
    return obj

# typeDict is a predefined list ObjectType records
tokyo = Location(name="tokyo", objectType=typeDict['location'])
tokyo = write(tokyo)

The error shows up as:

sqlalchemy.orm.exc.FlushError: Instance <Location at 0x10473a950> has a NULL identity key.

Full example available as a gist.



from SqlAlchemy - Classic Mapping Inheritance - Instance has Null Identity

No comments:

Post a Comment