need to write any changes, then the call to :meth:`_orm.Session.commit` would
be unnecessary.
+.. note::
+
+ Note that after :meth:`_orm.Session.commit` is called, either explicitly or
+ when using a context manager, all objects associated with the
+ :class:`.Session` are :term:`expired`, meaning their contents are erased to
+ be re-loaded within the next transaction. If these objects are instead
+ :term:`detached`, they will be non-functional until re-associated with a
+ new :class:`.Session`, unless the :paramref:`.Session.expire_on_commit`
+ parameter is used to disable this behavior. See the
+ section :ref:`session_committing` for more detail.
+
+
.. _session_begin_commit_rollback_block:
Framing out a begin / commit / rollback block
----------
:meth:`~.Session.commit` is used to commit the current
-transaction, if any. When there is no transaction in place, the method
-passes silently.
-
-When :meth:`_orm.Session.commit` operates upon the current open transaction,
-it first always issues :meth:`~.Session.flush`
-beforehand to flush any remaining state to the database; this is independent
-of the "autoflush" setting.
+transaction. At its core this indicates that it emits ``COMMIT`` on
+all current database connections that have a transaction in progress;
+from a :term:`DBAPI` perspective this means the ``connection.commit()``
+DBAPI method is invoked on each DBAPI connection.
+
+When there is no transaction in place for the :class:`.Session`, indicating
+that no operations were invoked on this :class:`.Session` since the previous
+call to :meth:`.Session.commit`, the method will begin and commit an
+internal-only "logical" transaction, that does not normally affect the database
+unless pending flush changes were detected, but will still invoke event
+handlers and object expiration rules.
+
+The :meth:`_orm.Session.commit` operation unconditionally issues
+:meth:`~.Session.flush` before emitting COMMIT on relevant database
+connections. If no pending changes are detected, then no SQL is emitted to the
+database. This behavior is not configurable and is not affected by the
+:paramref:`.Session.autoflush` parameter.
Subsequent to that, :meth:`_orm.Session.commit` will then COMMIT the actual
database transaction or transactions, if any, that are in place.
controlled by the :paramref:`_orm.Session.expire_on_commit` flag, which may be
set to ``False`` when this behavior is undesirable.
-.. versionchanged:: 1.4
-
- The :class:`_orm.Session` object now features deferred "begin" behavior, as
- described in :ref:`autobegin <session_autobegin>`. If no transaction is
- begun, methods like :meth:`_orm.Session.commit` and
- :meth:`_orm.Session.rollback` have no effect. This behavior would not
- have been observed prior to 1.4 as under non-autocommit mode, a
- transaction would always be implicitly present.
-
.. seealso::
:ref:`session_autobegin`
>>> session.commit()
COMMIT
+The above operation will commit the transaction that was in progress. The
+objects which we've dealt with are still :term:`attached` to the :class:`.Session`,
+which is a state they stay in until the :class:`.Session` is closed
+(which is introduced at :ref:`tutorial_orm_closing`).
+
+
+.. tip::
+
+ An important thing to note is that attributes on the objects that we just
+ worked with have been :term:`expired`, meaning, when we next access any
+ attributes on them, the :class:`.Session` will start a new transaction and
+ re-load their state. This option is sometimes problematic for both
+ performance reasons, or if one wishes to use the objects after closing the
+ :class:`.Session` (which is known as the :term:`detached` state), as they
+ will not have any state and will have no :class:`.Session` with which to load
+ that state, leading to "detached instance" errors. The behavior is
+ controllable using a parameter called :paramref:`.Session.expire_on_commit`.
+ More on this is at :ref:`tutorial_orm_closing`.
+
+
+
+
.. _tutorial_orm_updating:
Updating ORM Objects
[...] ('patrick',){stop}
True
+.. _tutorial_orm_closing:
Closing a Session
------------------
def commit(self) -> None:
"""Flush pending changes and commit the current transaction.
- If no transaction is in progress, the method will first
- "autobegin" a new transaction and commit.
+ When the COMMIT operation is complete, all objects are fully
+ :term:`expired`, erasing their internal contents, which will be
+ automatically re-loaded when the objects are next accessed. In the
+ interim, these objects are in an expired state and will not function if
+ they are :term:`detached` from the :class:`.Session`. Additionally,
+ this re-load operation is not supported when using asyncio-oriented
+ APIs. The :paramref:`.Session.expire_on_commit` parameter may be used
+ to disable this behavior.
+
+ When there is no transaction in place for the :class:`.Session`,
+ indicating that no operations were invoked on this :class:`.Session`
+ since the previous call to :meth:`.Session.commit`, the method will
+ begin and commit an internal-only "logical" transaction, that does not
+ normally affect the database unless pending flush changes were
+ detected, but will still invoke event handlers and object expiration
+ rules.
The outermost database transaction is committed unconditionally,
automatically releasing any SAVEPOINTs in effect.
:ref:`unitofwork_transaction`
+ :ref:`asyncio_orm_avoid_lazyloads`
+
"""
trans = self._transaction
if trans is None: