SqlAlchemy“ contains_eager”似乎未加载嵌套关系

时间:2019-08-12 22:42:24

标签: python python-2.7 sqlalchemy eager-loading

我的架构如下:

Thing # Base class for below tables
- id

Ball (Thing)
- color

Bin (Thing)
- ball -> Ball.id

Court (Thing)
- homeBin -> Bin.id
- awayBin -> Bin.id

我想确保每次加载一组Court时,它都包含最新的Ball列值。据我了解,contains_eager()可能可以帮助您解决此问题:

  

指示应从查询中手动说明的列中急切加载给定属性。

我有一个测试,每几秒钟查询一次任何Court秒。我发现,即使使用contains_eager,即使我在数据库中显式更新了列的值,我也只能看到Ball。color的相同值。

为什么sqlalchemy似乎可以重用这些旧数据?

以下是正在发生的事情的有效示例:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Thing(Base):
    __tablename__ = "Things"
    id = Column(Integer, primary_key=True)
    name = Column(String(256))
    thingType = Column(String(256))
    __mapper_args__ = {
            'with_polymorphic':'*',
            'polymorphic_on':"thingType",
            'polymorphic_identity':"thing"
        }


class Ball(Thing):
    __tablename__ = "Balls"
    id = Column('id', Integer, ForeignKey('Things.id'), primary_key=True)
    color = Column('color', String(256))
    __mapper_args__ = {
        'polymorphic_identity':'ball'
    }

class Bin(Thing):
    __tablename__ = "Bins"
    id = Column('id', Integer, ForeignKey('Things.id'), primary_key=True)
    shape = Column('shape', String(256))
    ballId = Column('ballId', Integer, ForeignKey('Balls.id'))
    ball = relationship(Ball, foreign_keys=[ballId], backref="outputBins")
    __mapper_args__ = {
        'polymorphic_identity':'bin'
    }
    pass

class Court(Thing):
    __tablename__ = "Courts"
    id = Column('id', Integer, ForeignKey('Things.id'), primary_key=True)
    homeBinId = Column('homeBinId', Integer, ForeignKey('Bins.id'))
    awayBinId = Column('awayBinId', Integer, ForeignKey('Bins.id'))
    homeBin = relationship(Bin, foreign_keys=[homeBinId], backref="homeCourts")
    awayBin = relationship(Bin, foreign_keys=[awayBinId], backref="awayCourts")
    __mapper_args__ = {
        'polymorphic_identity':'court'
    }

metadata = MetaData()
engine = create_engine("postgresql://localhost:5432/")
Session = sessionmaker(bind=engine)
session = Session()

def courtQuery():
    awayBalls = aliased(Ball, name="awayBalls")
    homeBalls = aliased(Ball, name="homeBalls")
    awayBins = aliased(Bin, name="awayBins")
    homeBins = aliased(Bin, name="homeBins")

    query = session.query(Court)\
        .outerjoin(awayBins, Court.awayBinId == awayBins.id)\
        .outerjoin(awayBalls, awayBins.ballId == awayBalls.id)\
        .outerjoin(homeBins, Court.homeBinId == homeBins.id)\
        .outerjoin(homeBalls, homeBins.ballId == homeBalls.id)\
        .options(contains_eager(Court.awayBin, alias=awayBins).contains_eager(awayBins.ball, alias=awayBalls))\
        .options(contains_eager(Court.homeBin, alias=homeBins).contains_eager(homeBins.ball, alias=homeBalls))
    return [r for r in query]

import time

while(True):
    results = courtQuery()
    court = results[0]
    ball = court.homeBin.ball
    print(ball.color) # does not change
    time.sleep(2)

环境:

  • Python 2.7.14
  • SqlAlchemy 1.3.0b1
  • PostGres 11.3(尽管我已经看过了 在Oracle上也是如此)

0 个答案:

没有答案