| [[docs]](rel:pooling) | | [[docs]](rel:types) |
+----------------------+ +----------------------------------+
-Above, the two most significant front-facing portions of SQLAlchemy are the **Object Relational Mapper** and the **SQL Construction Language**. These are two separate toolkits, one building off the other. SQL Expressions can be used independently of the ORM. When using the ORM, the SQL Expression language is used to establish object-relational configurations as well as in querying.
+Above, the two most significant front-facing portions of SQLAlchemy are the **Object Relational Mapper** and the **SQL Expression Language**. These are two separate toolkits, one building off the other. SQL Expressions can be used independently of the ORM. When using the ORM, the SQL Expression language is used to establish object-relational configurations as well as in querying.
## Tutorials
* [Object Relational Tutorial](rel:datamapping) - This describes the richest feature of SQLAlchemy, its object relational mapper. If you want to work with higher-level SQL which is constructed automatically for you, as well as management of Python objects, proceed to this tutorial.
- * [SQL Expression Tutorial](rel:sql) - The core of SQLAlchemy is its SQL expression language. The SQL construction language is a toolkit all its own, independent of the ORM package, which can be used to construct manipulable SQL expressions which can be programmatically constructed, modified, and executed, returning cursor-like result sets. It's a lot more lightweight than the ORM and is appropriate for higher scaling SQL operations. It's also heavily present within the ORM's public facing API, so advanced ORM users will want to master this language as well.
+ * [SQL Expression Tutorial](rel:sql) - The core of SQLAlchemy is its SQL expression language. The SQL Expression Language is a toolkit all its own, independent of the ORM package, which can be used to construct manipulable SQL expressions which can be programmatically constructed, modified, and executed, returning cursor-like result sets. It's a lot more lightweight than the ORM and is appropriate for higher scaling SQL operations. It's also heavily present within the ORM's public facing API, so advanced ORM users will want to master this language as well.
## Reference Documentation
>>> mapper(User, users_table) # doctest:+ELLIPSIS,+NORMALIZE_WHITESPACE
<sqlalchemy.orm.mapper.Mapper object at 0x...>
-The `mapper()` function creates a new `Mapper` object and stores it away for future reference. It also **instruments** the attributes on our `User` class, corresponding to the `users_table` table. The `id`, `name`, `fullname`, and `password` columns in our `users_table` are now instrumented upon our `User` class, meaning it will keep track of all changes to these attributes, and can save and load their values to/from the database. Lets create our first user, 'ed', and ensure that the object has all three of these attributes
+The `mapper()` function creates a new `Mapper` object and stores it away for future reference. It also **instruments** the attributes on our `User` class, corresponding to the `users_table` table. The `id`, `name`, `fullname`, and `password` columns in our `users_table` are now instrumented upon our `User` class, meaning it will keep track of all changes to these attributes, and can save and load their values to/from the database. Lets create our first user, 'Ed Jones', and ensure that the object has all three of these attributes:
{python}
>>> ed_user = User('ed', 'Ed Jones', 'edspassword')
>>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=engine, autoflush=True, transactional=True)
-If you don't have an `Engine` yet, but want to define `Session`, define it without `bind`, and set the `bind` parameter later:
+In the case where your application does not yet have an `Engine` when you define your module-level objects, just set it up like this:
{python}
>>> Session = sessionmaker(autoflush=True, transactional=True)
+
+Later, when you create your engine with `create_engine()`, connect it to `Session` like this:
+
>>> Session.configure(bind=engine) # once engine is available
This `Session` class will create new `Session` objects which are bound to our database and have some various transactional characteristics. Whenever you need to have a conversation with the database, you instantiate a `Session`:
['ed']
{stop}<User('ed','Ed Jones', 'edspassword')>
-And we get back our new user. If you view the generated SQL, you'll see that the `Session` issued an `INSERT` statement before querying for us. The `Session` stores whatever you put into it in memory, and at certain points in time issues a **flush**, which issues SQL to the database to store the object. You can also manually invoke this operation; however when the `Session` is configured to `autoflush`, its usually not needed.
+And we get back our new user. If you view the generated SQL, you'll see that the `Session` issued an `INSERT` statement before querying. The `Session` stores whatever you put into it in memory, and at certain points it issues a **flush**, which issues SQL to the database to store all pending new objects and changes to existing objects. You can manually invoke the flush operation using `flush()`; however when the `Session` is configured to `autoflush`, its usually not needed.
-OK, we'll lets do some more operations. Lets create and save three more users:
+OK, let's do some more operations. We'll create and save three more users:
{python}
>>> session.save(User('wendy', 'Wendy Williams', 'foobar'))
['fred', 'Fred Flinstone', 'blah']
COMMIT
-`commit()` flushes whatever remaining changes remain to the database, and commits the transaction. The connection resources referenced by the session are now returned to the connection pool. Subsequent operations with this session will then automatically be started in a **new** transaction, which will again re-acquire connection resources.
+`commit()` flushes whatever remaining changes remain to the database, and commits the transaction. The connection resources referenced by the session are now returned to the connection pool. Subsequent operations with this session will occur in a **new** transaction, which will again re-acquire connection resources when first needed.
-Lets take a look at Ed's `id` attribute again, just to make sure its set up:
+If we look at Ed's `id` attribute, which earlier was `None`, it now has a value:
{python}
>>> ed_user.id
1
-After each `INSERT` operation, the `Session` assigns all newly generated ids and defaults to the mapped object instance.
+After each `INSERT` operation, the `Session` assigns all newly generated ids and column defaults to the mapped object instance. For column defaults which are database-generated and are not part of the table's primary key, they'll be loaded when you first reference the attribute on the instance.
One crucial thing to note about the `Session` is that each object instance is cached within the Session, based on its primary key identitifer. The reason for this cache is not as much for performance as it is for maintaining an **identity map** of instances. This map guarantees that whenever you work with a particular `User` object in a session, **you always get the same instance back**. As below, reloading Ed gives us the same instance back:
['ed']
{stop}True
+Using the `get()` method, which queries based on primary key, will not issue any SQL to the database if the given key is already present:
+
+ {python}
+ >>> ed_user is session.query(User).get(ed_user.id)
+ True
+
## Querying
A whirlwind tour through querying.