将sqlalchemy集成到zope 3中

z3c.zalchem的Python项目详细描述


sqlalchemy和zope 3

“z3c.zalchemy”将对象关系映射器sqlalchemy集成到zope 3中 因为sqlos集成了sqlobject。

zalchemy尽量不干扰标准的sqlalchemy 用法。zalchemy的主要部分是sqlalchemy的集成 将事务转换为zope事务。这可以通过使用数据管理器来解决 它为每个新创建的线程加入zope事务。

Zalchemy使用来自Zope的两阶段提交系统。

这就是在zope中使用两阶段提交的方式。

  1. tpc_begin(txn)
  2. commit(txn)
  3. tpc_vote(txn)
  4. tpc_finish(txn)
  • commit执行session.flush(),它实际执行所有SQL语句。
  • tpc_finish()在sqlalchemy事务中执行transaction.commit()
  • tpc_abort()在sqlalchemy事务中执行transaction.rollback()

如果提交失败或另一个数据管理器失败,则数据未提交到 数据库。

重要

zope使用事务模块处理事务。Zalchemy插入 这个机制使用自己的数据管理器来使用zope的事务模块。

zalchemy提供方法z3c.zalchemy.getsession来获取sqlalchemy 会话对象。此方法确保会话连接到zope的 交易。

永远不要直接从sqlalchemy获取会话!

永远不要存储会话的实例也很重要。总是直接的 使用z3c.zalchemy.getsession。这是必要的,因为你不知道什么时候 交易已提交。提交总是使当前会话无效。 对getsession的新调用确保创建了新会话。

zalchemy类实现

与zope一起使用sqlalchemy没有区别。

Zalchemy提供了一种将表连接到数据库(引擎)的透明方法。

sqlalchemy引擎表示为实用程序:

>>> from z3c.zalchemy.datamanager import AlchemyEngineUtility
>>> engineUtility = AlchemyEngineUtility(
...       'database',
...       'sqlite:///%s'%dbFilename,
...       echo=False,
...       )

我们将表创建为普通的sqlalchemy表。重要的是 这里,必须使用来自zalchemy的元数据。请注意你 需要调用z3c.zalchemy.metadata。

>>> import sqlalchemy
>>> import z3c.zalchemy
>>> table3 = sqlalchemy.Table(
...     'table3',
...     z3c.zalchemy.metadata(),
...     sqlalchemy.Column('id', sqlalchemy.Integer,
...         sqlalchemy.Sequence('atable_id'), primary_key=True),
...     sqlalchemy.Column('value', sqlalchemy.Integer),
...     )

定义一个简单的类,该类稍后将用于映射到数据库表。

>>> class A(object):
...     pass

现在我们把桌子映射到我们班上。

>>> sqlalchemy.mapper(A, table3) is not None
True

为了让zalchemy完成它的工作,我们需要注册我们的数据库实用程序。

>>> from z3c.zalchemy.interfaces import IAlchemyEngineUtility
>>> from zope.component import provideUtility
>>> provideUtility(engineUtility, IAlchemyEngineUtility)

可以在不打开事务或会话的情况下创建表。 如果没有创建会话,则表的创建将推迟到下一个 调用zalchemy.getsession。

>>> z3c.zalchemy.createTable('table3', '')

Zalchemy自动协调Zope的事务管理器 sqlalchemy的会话。所有映射类都自动与 线程本地会话,它自动连接到一个特殊的 与Zope的事务协调的数据管理器。

>>> a = A()
>>> a.value = 1

提交事务将自动触发刷新并清除 会议。

>>> import transaction
>>> transaction.commit()

现在让我们尝试在一个新事务中恢复对象(我们在一个新事务中 已提交事务,因为已提交旧事务:

>>> from z3c.zalchemy.datamanager import getSession as session
>>> a = session().get(A, 1)
>>> a.value
1
>>> transaction.commit()

多个数据库

上面的例子假设只有一个数据库。数据库 引擎已注册为未命名的实用程序。未命名的实用程序总是 新会话的默认数据库。

这会自动将每个表分配给默认引擎。

对于多个数据库,可以将表分配给引擎。

我们创建了一个新的数据库引擎:

>>> engine2Util = AlchemyEngineUtility(
...     'engine2',
...     'sqlite:///%s'%dbFilename2,
...     echo=False,
...     )

因为已经有一个默认引擎,我们必须为 新引擎。

>>> provideUtility(engine2Util, IAlchemyEngineUtility, name='engine2')
>>> bTable = sqlalchemy.Table(
...     'bTable',
...     z3c.zalchemy.metadata(),
...     sqlalchemy.Column('id', sqlalchemy.Integer,
...         sqlalchemy.Sequence('btable_id'), primary_key=True),
...     sqlalchemy.Column('value', sqlalchemy.String),
...     )
>>> class B(object):
...     pass
>>> B.mapper = sqlalchemy.mapper(B, bTable)

将btable分配给新引擎并创建表。 这一次我们是在一个疗程内完成的。

>>> z3c.zalchemy.assignTable('bTable', 'engine2')
>>> z3c.zalchemy.createTable('bTable', 'engine2')
>>> b = B()
>>> b.value = 'b1'
>>> a = A()
>>> a.value = 321
>>> transaction.commit()
>>> a = session().get(A, 1)
>>> b = session().get(B, 1)
>>> str(b.value)
'b1'
>>> transaction.commit()

也可以将类分配给数据库:

>>> class Aa(object):
...     pass
>>> sqlalchemy.mapper(Aa, table3) is not None
True

现在我们可以将类分配给引擎:

>>> z3c.zalchemy.assignClass(Aa, 'engine2')

现在的问题是我们的发动机里没有桌子2英寸。 我们可以使用一个附加参数来创建表:

>>> z3c.zalchemy.createTable('table3', 'engine2')
>>> aa = Aa()
>>> aa.value = 100
>>> transaction.commit()

不同数据库中同名的表

如果我们有两个数据库,其中包含同名但带有 不同的结构我们需要把一个表明确地分配给一个数据库。这个 必须通过请求特定引擎的元数据来完成。

>>> b2Table = sqlalchemy.Table(
...     'bTable',
...     z3c.zalchemy.metadata('b2Engine'),
...     sqlalchemy.Column('id', sqlalchemy.Integer,
...         sqlalchemy.Sequence('btable_id'), primary_key=True),
...     sqlalchemy.Column('b2value', sqlalchemy.String),
...     )

我们现在可以通过提供引擎来请求该表。

>>> z3c.zalchemy.metadata.getTable('b2Engine', 'bTable', True)
Table('bTable',...

如果我们为“默认”引擎指定了一个表,那么我们可以请求 “b2engine”的“btable”,并回退到默认引擎。

>>> z3c.zalchemy.metadata.getTable('b2Engine', 'table3', True)
Table('table3',...

更改

0.2.2(2011-08-05)

  • Fix packaging problem: Declare namespace package ‘z3c’.

0.2.1-2007年11月13日

  • Conflict detection did not work with savepoints.

0.2-2007-09-27

  • Added a way to register database specific adapters for conflict detection and possible re-do by the publisher.

  • Using the threadlocal strategy of sqlalchemy instead of doing that ourselves.

  • Added support for optimistic savepoints. This can be used, similarly to what happens with ZODB, to flush intermediary work without committing.

  • Provide a tighter integration with Zope’s transaction mechanism. Sessions are now automatically associated with new objects. We rely on SQLAlchemy’s SessionContext object which hands out a session for each thread. Your code rarely should never have to call session.save(object) now.

    One incompatible change was introduced: You can not call getSession before registering an (unnamed) engine utility first. Doing so will raise a ValueError.

0.1.1-2007-06-27

  • Fixed a failing test in TRANSACTION.txt where an exception demonstrated a string being returned but it was a unicode string.

0.1-从未释放

  • This was supposed to be the first release, but we missed a broken test. See 0.1.1

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何使用JNA创建同一库的多个实例?   java在将Graphql查询作为JSON字符串传递时收到意外的令牌错误   OAuth2 oltu的java问题   java桌面应用程序使用的好的嵌入式数据库是什么?   java Firebase数据库高级查询选项   java正在使磁盘上的EhCache元素过期   java 安卓还原处于backstack中的片段的实例状态   XMemcached中的java异步集   java TimescaleDB是否使用与Postgresql完全相同的JDBC驱动程序?   java从网站c读取信息#   检查java Android中的字符串是否只包含数字和空格   c#如何向web服务发送特殊字符?   grails无法调用需要java的方法。lang.类参数?   java我在组合框中调用的方法不会运行所有代码,它只运行部分代码   java发送带有标头的HTTP GET请求