gpt4 book ai didi

mysql - 使用关联表时查询导致commit

转载 作者:行者123 更新时间:2023-11-29 00:49:27 25 4
gpt4 key购买 nike

谁能帮我理解以下行为?我有一个简单的模式,其中一个项目有很多 Assets 和元素。 Assets 和元素在项目范围内具有多对多关系。

我需要确保元素具有在项目范围内唯一的代码,因此在将新元素添加到 SQLAlchemy session 之前,我想检查是否已经存在具有相同代码的元素在项目中。我发现的是,当我使用关联表来映射元素和 Assets 之间的多对多关系时,如果查询操作实际上将新元素提交给数据库,我就无法查询数据库。

明确地说,此时我还没有add 编辑或提交 编辑这个新元素到 SQLAlchemy session 。

from sqlalchemy import create_engine, and_
from sqlalchemy import Table, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relation, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy

### your credentials here ###
# _MYSQL_DB =
# _MYSQL_USER =
# _MYSQL_PWORD =
# _MYSQL_SCHEMATA =
# _MYSQL_TEST_SCHEMATA =

testEngine = create_engine("mysql://%s:%s@%s/%s"%( _MYSQL_USER,
_MYSQL_PWORD,
_MYSQL_DB,
_MYSQL_TEST_SCHEMATA),
pool_recycle=3600,
echo=True)

Base = declarative_base()
SQLAlchemySession = sessionmaker(autoflush=True, autocommit=False)

class Project(Base):
__tablename__ = "SA_project_t"
id = Column(Integer, primary_key=True, autoincrement=True)
code = Column(String(24), nullable=False, unique=True)

class Asset(Base):
__tablename__ = "SA_asset_t"
id = Column(Integer, primary_key=True, autoincrement=True)
projectId = Column(Integer, ForeignKey("SA_project_t.id"))
project = relation("Project")
code = Column(String(128))

element_to_asset_assoc = Table( "SA_elementToAssetAssoc_t",
Base.metadata,
Column("elementId", Integer, ForeignKey("SA_element_t.id")),
Column("assetId", Integer, ForeignKey("SA_asset_t.id")))

class Element(Base):
__tablename__ = "SA_element_t"
id = Column(Integer, primary_key=True, autoincrement=True)
projectId = Column(Integer, ForeignKey("SA_project_t.id"))
project = relation("Project")
code = Column(String(256))
assets = relation("Asset", secondary=element_to_asset_assoc, backref="elements")


Base.metadata.bind=testEngine
session = SQLAlchemySession(bind=testEngine)

Base.metadata.drop_all(checkfirst=True)
Base.metadata.create_all(testEngine, checkfirst=True)

# Create a Project, Asset and Element

project = Project()
project.code = "MyProject"
session.add(project)

asset = Asset()
asset.project = project
asset.code = "MyAsset"
session.add(asset)

element = Element()
element.project = project
element.code = "MyElement"
element.assets = [asset]
session.add(element)

session.commit()

# Now I'd like to add a new element, but first check that the
# element's code is unique within the scope of the Project

newElement = Element()
newElement.project = project
newElement.code = "MyElement"
newElement.assets = [asset]

results = session.query(Element).filter(and_( Element.project==newElement.project,
Element.code==newElement.code))

# Up until this point, newElement hasn't been inserted into the
# database, but once I query "results.count()" I find that an INSERT
# has been perfomed.

print results.count()

# p.s. I realize that results will contain both the original and
# new element, but I don't expect the new element to have been
# inserted into the database at this point.

results 变量上调用count() 的操作是将newElement 提交给MySQL 数据库,这不是我的本意。如果删除关联表,则会得到预期的行为 - newElement 不会添加到数据库中。

从日志中我可以看出, session 在查询开始时将关联的 Assets 视为脏 Assets ,刷新它会触发 newElement 的提交。这是预期的行为吗?如果是这样,有没有办法保持多对多关系,同时在这些情况下仍然查询数据库并且触发提交。

使用 SQLAlchemy 0.7.4

最佳答案

不需要 add() newElement 对象,因为当您将绑定(bind)对象分配给它的关系之一时,它会自动添加到 session 中。当访问 newElement.project 属性时,它被刷新到数据库(您可以使用 autoflush=False 来禁用此行为)。 MySQL 默认使用 MyISAM 引擎,忽略事务语句。因此,所有刷新的更改都会持续存在。要启用事务支持,请将 __table_args__ = {'mysql_engine': 'InnoDB'} 添加到您的映射类。

关于mysql - 使用关联表时查询导致commit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9168466/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com