{"id":21902,"date":"2022-10-28T08:02:44","date_gmt":"2022-10-28T15:02:44","guid":{"rendered":"https:\/\/coderpad.io\/?p=21902"},"modified":"2023-06-05T13:57:13","modified_gmt":"2023-06-05T20:57:13","slug":"understanding-transactions-in-sqlalchemy","status":"publish","type":"post","link":"https:\/\/coderpad.io\/blog\/development\/understanding-transactions-in-sqlalchemy\/","title":{"rendered":"Understanding Transactions in SQLAlchemy"},"content":{"rendered":"\n<p>Database transaction in SQLAlchemy follows the rule of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Acid\" target=\"_blank\" rel=\"noopener\">ACID<\/a> in relational databases. This tutorial shows how to understand transactions in a practical application. You&#8217;re going to learn why SQLAlchemy transactions matter in building applications like getting orders from an inventory.<\/p>\n\n\n\n<p>You can use your own IDE and dependencies to try things out, and as always, this tutorial will use the already prepared environment, <a href=\"https:\/\/app.coderpad.io\/sandbox\">CoderPad sandbox<\/a>, which has all that you need from the dependencies in this application.<\/p>\n\n\n\n<p>Configure your sandbox by selecting the Python 3 language environment. On the top left corner, click on the three dots and select the SQLAlchemy ( Postgres ) adapter from the list of database adapters.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\u2139\ufe0f If this is your first time working with SQLAlchemy then you should check out <a href=\"https:\/\/coderpad.io\/blog\/development\/sqlalchemy-with-postgresql\/\">How to Interact with Databases using SQLAlchemy with PostgreSQL<\/a>.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Create the database engine<\/strong><\/h2>\n\n\n\n<p>Start with creating the SQLAlchemy database engine, which is the <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/core\/engines.html\" target=\"_blank\" rel=\"noopener\">home base for the actual database<\/a> and the DBAPI. The DBAPI (Python Database API Specification) is the low-level API accessed by Python to be able to communicate with the database. <\/p>\n\n\n\n<p>In our case, we&#8217;ll use <code>pyscopg2<\/code>, the DBAPI for PostgreSQL. See below how to establish the engine:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> sqlalchemy <span class=\"hljs-keyword\">import<\/span> create_engine\n<span class=\"hljs-keyword\">from<\/span> sqlalchemy.engine <span class=\"hljs-keyword\">import<\/span> URL\n\nurl = URL.create(\n    drivername=<span class=\"hljs-string\">\"postgresql\"<\/span>\n    username=<span class=\"hljs-string\">\"coderpad\"<\/span>,\n    host=<span class=\"hljs-string\">\"\/tmp\/postgresql\/socket\"<\/span>\n    database=<span class=\"hljs-string\">\"coderpad\"<\/span>)\nengine = create_engine(url)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>url<\/code> instance has established the database configuration to talk to the CoderPad database. Feel free to update your own <code>url<\/code> if you&#8217;re not using the CoderPad sandbox.<\/p>\n\n\n\n<p>Now, the engine is the starting point for our PostgreSQL database communication.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Create the session instance<\/strong><\/h2>\n\n\n\n<p>To interact with the database through <code>SELECT<\/code> statements and other queries, you need to instantiate an <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/orm\/session_basics.html\" target=\"_blank\" rel=\"noopener\">SQLAlchemy session<\/a>. Instantiate it with the engine that you defined earlier:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> sqlalchemy.orm <span class=\"hljs-keyword\">import<\/span> sessionmaker\n\nSession = sessionmaker(bind=engine)\nsession = Session()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This <code>session<\/code> instance is what you need to do Object Relational Mapping (ORM) operations to emit <a href=\"https:\/\/coderpad.io\/blog\/development\/sql-functions-and-techniques-every-data-person-should-know\/\">SQL statements<\/a> like <code>SELECT<\/code>, <code>INSERT<\/code>, <code>UPDATE<\/code>, and <code>DELETE<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Define the database model<\/strong><\/h2>\n\n\n\n<p>This inventory application is inspired by the <a href=\"https:\/\/github.com\/pthom\/northwind_psql\" target=\"_blank\" rel=\"noopener\">Northwind database<\/a>. You can consult the GitHub repo to explore the schema. We need only four tables for our minimal version: <code>customers<\/code>, <code>products<\/code>, <code>orders<\/code>, and <code>order_details<\/code>.<\/p>\n\n\n\n<p>Create a new base class (Base instance) to initiate a declarative mapping to all classes that inherit from it. The example below shows how to inherit the first class representing the <code>customers<\/code> table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> sqlalchemy <span class=\"hljs-keyword\">import<\/span> Column, String\n<span class=\"hljs-keyword\">from<\/span> sqlalchemy.orm <span class=\"hljs-keyword\">import<\/span> declarative_base, relationship\n\n\nBase = declarative_base()\n\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Customer<\/span><span class=\"hljs-params\">(Base)<\/span>:<\/span>\n\u00a0 \u00a0 __tablename__ = <span class=\"hljs-string\">'customers'<\/span>\n\n\u00a0 \u00a0 customer_id = Column(String(<span class=\"hljs-number\">5<\/span>), primary_key=<span class=\"hljs-literal\">True<\/span>)\n\u00a0 \u00a0 company_name = Column(String(<span class=\"hljs-number\">30<\/span>))\n\u00a0 \u00a0 contact_name = Column(String(<span class=\"hljs-number\">30<\/span>))\n\u00a0 \u00a0 country = Column(String(<span class=\"hljs-number\">15<\/span>))\n\n\u00a0 \u00a0 orders = relationship(<span class=\"hljs-string\">'Order'<\/span>, backref=<span class=\"hljs-string\">'customer'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, the customers table is defined and has metadata of the customer info. This Customer class back-references customer into the orders table. We&#8217;ll see how to create a foreign key in the orders table.<\/p>\n\n\n\n<p>If you want to get deeper with defining the data models, you can consult <a href=\"https:\/\/coderpad.io\/blog\/development\/sqlalchemy-with-postgresql\/\">this SQLAlchemy interaction with database article<\/a>.<\/p>\n\n\n\n<p>Below is the definition of the other three tables:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> sqlalchemy <span class=\"hljs-keyword\">import<\/span> Integer, Boolean, ForeignKey, CheckConstraint\n\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Product<\/span><span class=\"hljs-params\">(Base)<\/span>:<\/span>\n\u00a0 \u00a0 __tablename__ = <span class=\"hljs-string\">'products'<\/span>\n\u00a0 \u00a0 __table_args__ = (CheckConstraint(\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-string\">'unit_quantity&gt;=0'<\/span>,\n\u00a0 \u00a0 \u00a0 \u00a0 <span class=\"hljs-string\">'quantity should exist in the inventory'<\/span>\n\u00a0 \u00a0 \u00a0 \u00a0 ),)\n\n\u00a0 \u00a0 id = Column(Integer(), primary_key=<span class=\"hljs-literal\">True<\/span>)\n\u00a0 \u00a0 product_name = Column(String(<span class=\"hljs-number\">40<\/span>), nullable=<span class=\"hljs-literal\">False<\/span>)\n\u00a0 \u00a0 unit_quantity = Column(Integer(), nullable=<span class=\"hljs-literal\">False<\/span>)\n\n\u00a0 \u00a0 order_details = relationship(<span class=\"hljs-string\">'OrderDetail'<\/span>, backref=<span class=\"hljs-string\">'product'<\/span>)\n\u00a0 \u00a0\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Order<\/span><span class=\"hljs-params\">(Base)<\/span>:<\/span>\n\u00a0 \u00a0 __tablename__ = <span class=\"hljs-string\">'orders'<\/span>\n\n\u00a0 \u00a0 id = Column(Integer(), primary_key=<span class=\"hljs-literal\">True<\/span>)\n\u00a0 \u00a0 customer_id = Column(String(<span class=\"hljs-number\">5<\/span>), ForeignKey(<span class=\"hljs-string\">'customers.customer_id'<\/span>))\n\u00a0 \u00a0 shipped = Column(Boolean(), default=<span class=\"hljs-literal\">False<\/span>)\n\u00a0 \u00a0 order_details = relationship(<span class=\"hljs-string\">'OrderDetail'<\/span>, backref=<span class=\"hljs-string\">'order'<\/span>)\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">OrderDetail<\/span><span class=\"hljs-params\">(Base)<\/span>:<\/span>\n\u00a0 \u00a0 __tablename__ = <span class=\"hljs-string\">'order_details'<\/span>\n\n\u00a0 \u00a0 id = Column(Integer(), primary_key=<span class=\"hljs-literal\">True<\/span>)\n\u00a0 \u00a0 order_id = Column(Integer(), ForeignKey(<span class=\"hljs-string\">'orders.id'<\/span>))\n\u00a0 \u00a0 product_id = Column(Integer(), ForeignKey(<span class=\"hljs-string\">'products.id'<\/span>))\n\u00a0 \u00a0 unit_price = Column(Integer(), nullable=<span class=\"hljs-literal\">False<\/span>)\n\u00a0 \u00a0 quantity = Column(Integer(), nullable=<span class=\"hljs-literal\">False<\/span>)\n\nBase.metadata.create_all(engine)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The products table is defined with the product name and quantity per unit and the order details, which back-references product instance into the <code>order_details<\/code> table. This means the <code>orders_details<\/code> table would have a <code>product<\/code> column which should refer to a product field in the products table. Similarly, there is an <code>order_details<\/code> column in the products table, which should contain the order details\/items of each product.<\/p>\n\n\n\n<p>The constraint defined in the <code>__table_arg__<\/code> metadata ensures that the unit quantity equals or exceeds zero. If the unit quantity is  zero, it means the product is finished and no longer exists in the inventory. If it&#8217;s bigger than zero, it means the product has a specific quantity in the inventory.<\/p>\n\n\n\n<p>The <code>orders<\/code> table is defined with a shipped boolean value to indicate whether the product is shipped or not. It has the <code>order_details<\/code> back-referencing order to the <code>order_details<\/code> table. The orders table has <code>customer_id<\/code> as a foreign key to refer to the customers table.<\/p>\n\n\n\n<p>Finally, the <code>order_details<\/code> table has metadata of <code>order_id<\/code> as a foreign key to the orders table, <code>product_id<\/code> as a foreign key to the products table, <code>unit_price<\/code> as a price for a product unit, and quantity to show the ordered quantity of the product that the customer has ordered.<\/p>\n\n\n\n<p>All these objects (or tables) are created with the last command using <code>Base.metadata.create_all(engine)<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Inserting data<\/strong><\/h2>\n\n\n\n<p>Now, you can insert data to define customers, products, orders, and order details. The examples below illustrate data insertions for our inventory app:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">alfki = Customer(\n    customer_id = <span class=\"hljs-string\">'ALFKI'<\/span>,\n\u00a0 \u00a0 company_name = <span class=\"hljs-string\">'Around the Horn'<\/span>,\n\u00a0 \u00a0 contact_name = <span class=\"hljs-string\">'Thomas Hardy'<\/span>,\n\u00a0 \u00a0 country=<span class=\"hljs-string\">'UK'<\/span>\n)\n\nproduct_chai = Product(\n\u00a0 \u00a0 product_name=<span class=\"hljs-string\">'Chai'<\/span>,\n\u00a0 \u00a0 unit_quantity=<span class=\"hljs-number\">12<\/span>\n\u00a0 \u00a0 )\n\nproduct_syrup = Product(\n\u00a0 \u00a0 product_name=<span class=\"hljs-string\">'Anissed Syrup'<\/span>,\n\u00a0 \u00a0 unit_quantity=<span class=\"hljs-number\">2<\/span>\n\u00a0 \u00a0 )\n\nalfki_order1 = Order(customer = alfki)\n\norder1_items = OrderDetail(\n\u00a0 \u00a0 order = alfki_order1,\n\u00a0 \u00a0 product = product_chai,\n\u00a0 \u00a0 unit_price = <span class=\"hljs-number\">18<\/span>,\n\u00a0 \u00a0 quantity = <span class=\"hljs-number\">8<\/span>\n)\n\nalfki_order2 = Order(customer = alfki)\n\norder2_items_chai = OrderDetail(\n\u00a0 \u00a0 order = alfki_order2,\n\u00a0 \u00a0 product = product_chai,\n\u00a0 \u00a0 unit_price = <span class=\"hljs-number\">18<\/span>,\n\u00a0 \u00a0 quantity = <span class=\"hljs-number\">3<\/span>\n)\n\norder2_items_syrup = OrderDetail(\n\u00a0 \u00a0 order = alfki_order2,\n\u00a0 \u00a0 product = product_syrup,\n\u00a0 \u00a0 unit_price = <span class=\"hljs-number\">10<\/span>,\n\u00a0 \u00a0 quantity = <span class=\"hljs-number\">5<\/span>\n)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So we have 12 chai products and 2 anissed syrups. Alfki customer placed two orders. The first order is 8 chai while the second order consists of 3 chai and 5 anissed syrup.<\/p>\n\n\n\n<p>After defining each object with the related table, you can now add the orders and order details in the database using the <code>.add_all()<\/code> method. Then you can commit all these changes to the database:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.add_all<\/span>(<span class=\"hljs-selector-attr\">&#91;alfki_order1, order1_items, alfki_order2, order2_items_chai, order2_items_syrup]<\/span>)\n<span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.commit<\/span>()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Note how elegant and easy SQLAlchemy ORM is when inserting data. Every insertion is stored and operated as if it were a native Python object. Database relationships are all respected <strong>and<\/strong> a Python developer never has to write a bunch of insertion lines of SQL.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Implement the transaction logic<\/strong><\/h2>\n\n\n\n<p>Now is the time to ship the order defined by the order id. The following function shows the logic for shipping the order which represents the transaction in the database:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">ship_order<\/span><span class=\"hljs-params\">(order_id)<\/span>:<\/span>\n\u00a0 \u00a0 products_to_ship = session.query(OrderDetail).filter(OrderDetail.order_id == order_id)\n\n\u00a0 \u00a0 <span class=\"hljs-keyword\">for<\/span> product <span class=\"hljs-keyword\">in<\/span> products_to_ship:\n\u00a0 \u00a0 \u00a0 \u00a0 print(<span class=\"hljs-string\">f\"Product: <span class=\"hljs-subst\">{product.product_id}<\/span>. Quantity: <span class=\"hljs-subst\">{product.quantity}<\/span>.\"<\/span>)\n\u00a0 \u00a0 \u00a0 \u00a0 ordered_product = session.query(Product).filter(Product.id == product.product_id).first()\n\u00a0 \u00a0 \u00a0 \u00a0 ordered_product.unit_quantity -= product.quantity\n\n\u00a0 \u00a0 shipped_order = session.query(Order).filter(Order.id == order_id)\n\u00a0 \u00a0 shipped_order.shipped = <span class=\"hljs-literal\">True<\/span>\n\u00a0 \u00a0 session.commit()\n\u00a0 \u00a0\n\u00a0 \u00a0 print(<span class=\"hljs-string\">f\"Your order is shipped. ID is: <span class=\"hljs-subst\">{order_id}<\/span>\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you can see, the <code>products_to_ship<\/code> object is a Query object which selects records from the <code>order_details<\/code> table that match the <code>order_id<\/code> column.<\/p>\n\n\n\n<p>The for loop that follows is looping over each product that should be shipped. The <code>ordered_product<\/code> object is the product record that is requested to be shipped. We then subtract the ordered quantity of the product from the actual quantity that exists in the inventory.<\/p>\n\n\n\n<p>The <code>shipped_order<\/code> is the requested order record from the orders table. We mark the status of the shipped boolean value as True. Finally, we commit the changes to the database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Manage transactions<\/strong><\/h2>\n\n\n\n<p>Transactions to the database will be clear to you starting from this section. To understand what&#8217;s happening to the database, let&#8217;s track the product quantity number before and after the order is placed:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">print(session.query(Product.product_name, Product.unit_quantity).all())\n\nship_order(<span class=\"hljs-number\">1<\/span>)\n\nprint(session.query(Product.product_name, Product.unit_quantity).all())<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output from the query above is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-attr\">&#91;(<span class=\"hljs-string\">'Chai'<\/span>, 12), (<span class=\"hljs-string\">'Anissed Syrup'<\/span>, 2)]<\/span>\n<span class=\"hljs-selector-tag\">Product<\/span>: 1. <span class=\"hljs-selector-tag\">Quantity<\/span>: 8.\n<span class=\"hljs-selector-tag\">Your<\/span> <span class=\"hljs-selector-tag\">order<\/span> <span class=\"hljs-selector-tag\">is<\/span> <span class=\"hljs-selector-tag\">shipped<\/span>. <span class=\"hljs-selector-tag\">ID<\/span> <span class=\"hljs-selector-tag\">is<\/span>: 1\n<span class=\"hljs-selector-attr\">&#91;(<span class=\"hljs-string\">'Anissed Syrup'<\/span>, 2), (<span class=\"hljs-string\">'Chai'<\/span>, 4)]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you can see, we ordered 8 products of product id of 1 (the Chai product). After the order is placed, the Chai quantity in our inventory becomes 4 (8 subtracted from 12).<\/p>\n\n\n\n<p>Now, hit the <em>Reset<\/em> button on the right corner of the CoderPad sandbox and then ship the second order.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\u2139\ufe0f We&#8217;re resetting the environment to remove any change to the current session that happened in our database. You may want to remove the four tables if you&#8217;re not following along on the Pad sandbox.<\/p>\n<\/blockquote>\n\n\n\n<p>Add the following <code>ship_order(2)<\/code> line:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">print(session.query(Product.product_name, Product.unit_quantity).all())\n\nship_order(<span class=\"hljs-number\">1<\/span>)\nship_order(<span class=\"hljs-number\">2<\/span>)\n\nprint(session.query(Product.product_name, Product.unit_quantity).all())<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Before executing the last updated code, remember the second order. It consists of two products; 3 chai and 5 anissed syrup quantities. However, there are 12 chai and only 3 anissed syrup products in the inventory. This means after placing the second order, there is more demand for anissed syrup than the already supplied product in the inventory.<\/p>\n\n\n\n<p>So if you run the code, you&#8217;ll see the following error:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">IntegrityError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint <span class=\"hljs-string\">\"customers_pkey\"<\/span>\n<span class=\"hljs-attr\">DETAIL<\/span>:  Key (customer_id)=(ALFKI) already exists.\n\n&#91;SQL: INSERT INTO customers (customer_id, company_name, contact_name, country) VALUES (%(customer_id)s, %(company_name)s, %(contact_name)s, %(country)s)]\n&#91;parameters: {<span class=\"hljs-string\">'customer_id'<\/span>: <span class=\"hljs-string\">'ALFKI'<\/span>, <span class=\"hljs-string\">'company_name'<\/span>: <span class=\"hljs-string\">'Around the Horn'<\/span>, <span class=\"hljs-string\">'contact_name'<\/span>: <span class=\"hljs-string\">'Thomas Hardy'<\/span>, <span class=\"hljs-string\">'country'<\/span>: <span class=\"hljs-string\">'UK'<\/span>}]\n(Background on <span class=\"hljs-keyword\">this<\/span> error at: https:<span class=\"hljs-comment\">\/\/sqlalche.me\/e\/14\/gkpj)<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The error shows an <code>IntegrityError<\/code> exception because it violates the rule we set for the quantity attribute in the products table.<\/p>\n\n\n\n<p>The problem here does not only exist for this particular order. It also exists for the following orders. Say, another order is placed ordering another Chai from the same customer, Alfki:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">alfki_order3 = Order(customer = alfki)\n\norder3_items = OrderDetail(\n    order = alfki_order3,\n    product = product_chai,\n    unit_price = <span class=\"hljs-number\">18<\/span>,\n    quantity = <span class=\"hljs-number\">1<\/span>\n)\n\nsession.add_all(&#91;alfki_order3, order3_items])\nsession.commit()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\u2139\ufe0f Put the previous snippet to the REPL python window on the right of the Pad sandbox.<\/p>\n<\/blockquote>\n\n\n\n<p>When you commit any change to the database like the above, you&#8217;ll get the following error:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">raise sa_exc.PendingRollbackError(PendingRollbackError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was...<\/code><\/span><\/pre>\n\n\n<p>This <code>PendingRollbackError<\/code> shows that the last transaction to the database was not successful. So you need to roll it back to the session first:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">session.rollback()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To request an order of the third order:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">print(session.query(Product.product_name, Product.unit_quantity).all())\n\nship_order(<span class=\"hljs-number\">3<\/span>)\n\nprint(session.query(Product.product_name, Product.unit_quantity).all())<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now the database transaction has been committed to the database:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-attr\">&#91;(<span class=\"hljs-string\">'Anissed Syrup'<\/span>, 2), (<span class=\"hljs-string\">'Chai'<\/span>, 4)]<\/span>\n<span class=\"hljs-selector-tag\">Product<\/span>: 1. <span class=\"hljs-selector-tag\">Quantity<\/span>: 1.\n<span class=\"hljs-selector-tag\">Your<\/span> <span class=\"hljs-selector-tag\">order<\/span> <span class=\"hljs-selector-tag\">is<\/span> <span class=\"hljs-selector-tag\">shipped<\/span>. <span class=\"hljs-selector-tag\">ID<\/span> <span class=\"hljs-selector-tag\">is<\/span>: 4\n<span class=\"hljs-selector-attr\">&#91;(<span class=\"hljs-string\">'Anissed Syrup'<\/span>, 2), (<span class=\"hljs-string\">'Chai'<\/span>, 3)]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>But this was an ad-hoc fix to the pending rollback error using the <code>session.rollback()<\/code>. We want to catch this error whenever there is a violation of the database transaction. So use <code>try\/except<\/code> and then roll back the session in the except block.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>SQLAlchemy rollback<\/strong><\/h2>\n\n\n\n<p>To do a rollback in the SQLAlchemy ORM, use <code>session.rollback()<\/code>. Let&#8217;s revamp the <code>ship_order()<\/code> function to adapt the new try\/except statement:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">ship_order<\/span><span class=\"hljs-params\">(order_id)<\/span>:<\/span>\n    <span class=\"hljs-comment\"># ...<\/span>\n    shipped_order.shipped = <span class=\"hljs-literal\">True<\/span>\n    <span class=\"hljs-keyword\">try<\/span>:\n        session.commit()\n    <span class=\"hljs-keyword\">except<\/span> IntegrityError <span class=\"hljs-keyword\">as<\/span> e:\n        print(<span class=\"hljs-string\">f\"QuantityViolationError: <span class=\"hljs-subst\">{e.orig}<\/span>\"<\/span>)\n        session.rollback()\n\n    print(<span class=\"hljs-string\">f\"Your order is shipped. ID is: <span class=\"hljs-subst\">{order_id}<\/span>\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, let&#8217;s place the two orders with the new change. Hit Reset and then hit Run and see the output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">&#91;(<span class=\"hljs-string\">'Chai'<\/span>, <span class=\"hljs-number\">12<\/span>), (<span class=\"hljs-string\">'Anissed Syrup'<\/span>, <span class=\"hljs-number\">2<\/span>)]\n<span class=\"hljs-attr\">Product<\/span>: <span class=\"hljs-number\">1.<\/span> Quantity: <span class=\"hljs-number\">8.<\/span>\nYour order is shipped. ID is: <span class=\"hljs-number\">1<\/span>\n<span class=\"hljs-attr\">Product<\/span>: <span class=\"hljs-number\">1.<\/span> Quantity: <span class=\"hljs-number\">3.<\/span>\n<span class=\"hljs-attr\">Product<\/span>: <span class=\"hljs-number\">2.<\/span> Quantity: <span class=\"hljs-number\">5.<\/span>QuantityViolationError: <span class=\"hljs-keyword\">new<\/span> row <span class=\"hljs-keyword\">for<\/span> relation <span class=\"hljs-string\">\"products\"<\/span> violates check co\nnstraint <span class=\"hljs-string\">\"quantity should exist in the inventory\"<\/span>\n<span class=\"hljs-attr\">DETAIL<\/span>:  Failing row contains (<span class=\"hljs-number\">2<\/span>, Anissed Syrup, <span class=\"hljs-number\">-3<\/span>).\n\nYour order is shipped. ID is: <span class=\"hljs-number\">2<\/span>\n&#91;(<span class=\"hljs-string\">'Anissed Syrup'<\/span>, <span class=\"hljs-number\">2<\/span>), (<span class=\"hljs-string\">'Chai'<\/span>, <span class=\"hljs-number\">4<\/span>)]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>As you can see, the first order is placed and ready to be shipped. However, the second order is rolled back. So the transaction has not been completed, and there is no change to the quantity of the products.<\/p>\n\n\n\n<p>This means if you place any other order, it will be transacted as long as it satisfies the constraints, as in the case of the unit quantity constraint.<\/p>\n\n\n\n<p>If you placed the third order that we wrote above and committed it to the database, and then shipped this order using the <code>ship_order(3)<\/code>, you&#8217;d see a successful commit to the database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>SQLAlchemy commit vs flush<\/strong><\/h2>\n\n\n\n<p>Session in SQLAlchemy ORM is the start of any transaction. It means you can insert, delete, or update records in the database through the session. If you want to add a new change to the database, you&#8217;ll first use <code>session.add()<\/code>, which <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/orm\/session_basics.html#adding-new-or-existing-items\" target=\"_blank\" rel=\"noopener\">places this new instance<\/a> in the session object. The new instance is not <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/glossary.html#term-persistent\" target=\"_blank\" rel=\"noopener\">persistent<\/a> in the database until it&#8217;s committed.<\/p>\n\n\n\n<p>When you commit that instance to the database using <code>session.commit()<\/code>, and you&#8217;re doing two things under the hood:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Flushing the database with that new change so that you can query from the session object<\/li>\n\n\n\n<li>Committing the new change to the database so that the database is updated with this new change<\/li>\n<\/ol>\n\n\n\n<p>So the <code>session.commit()<\/code> calls <code>session.flush()<\/code> by default. To make it more clear, let&#8217;s first delete the third order from the database (if you committed that change already to the database):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.delete<\/span>(<span class=\"hljs-selector-tag\">alfki_order3<\/span>)\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.delete<\/span>(<span class=\"hljs-selector-tag\">order3_items<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, <code>alfki_order3<\/code> is just a Python object. Not attached to the session object, which means it&#8217;s in a <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/glossary.html#term-detached\" target=\"_blank\" rel=\"noopener\">detached<\/a> state. To check if the third order is already deleted, run the following:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.query<\/span>(<span class=\"hljs-selector-tag\">Order<\/span><span class=\"hljs-selector-class\">.id<\/span>)<span class=\"hljs-selector-class\">.all<\/span>()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You&#8217;ll see only the first and second orders.<\/p>\n\n\n\n<p>Before you add these <code>aflki_order3<\/code> and <code>order3_items<\/code> objects again to the session, you need to return their object state to <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/glossary.html#term-transient\" target=\"_blank\" rel=\"noopener\">transient<\/a>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> sqlalchemy.orm <span class=\"hljs-keyword\">import<\/span> make_transient\n\n&gt;&gt;&gt; make_transient(alfki_order3)\n&gt;&gt;&gt; make_transient(order3_items)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The transient state is where the object is not associated yet with the session.<\/p>\n\n\n\n<p>The <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/orm\/session_api.html#sqlalchemy.orm.make_transient\" target=\"_blank\" rel=\"noopener\">given mapped instances<\/a> <code>alfki_order3<\/code> and <code>order3_items<\/code> were in the detached state. That&#8217;s why you used <code>make_transient<\/code>.<\/p>\n\n\n\n<p>You can add them back to the session:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.add_all<\/span>(<span class=\"hljs-selector-attr\">&#91;alfki_order3, order3_items]<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Before committing the new changes to the database, you can query those changes from the session. That&#8217;s because the <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/orm\/session_basics.html#session-flushing\" target=\"_blank\" rel=\"noopener\">autoflush<\/a> is enabled by default when you declare a session. A quick check would be querying from the orders table:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.query<\/span>(<span class=\"hljs-selector-tag\">Order<\/span><span class=\"hljs-selector-class\">.id<\/span>)<span class=\"hljs-selector-class\">.all<\/span>()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You&#8217;ll see the third order is included.<\/p>\n\n\n\n<p>To disable <code>autoflush<\/code>, assign the <code>autoflush<\/code> session attribute to False:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">&gt;&gt;&gt; session.autoflush = <span class=\"hljs-keyword\">False<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Let&#8217;s experiment with how you can force a flush. Delete the two objects, convert their object states to transient, and then add both back to the session:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.delete<\/span>(<span class=\"hljs-selector-tag\">alfki_order3<\/span>)\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.delete<\/span>(<span class=\"hljs-selector-tag\">order3_items<\/span>)\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">make_transient<\/span>(<span class=\"hljs-selector-tag\">alfki_order3<\/span>)\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">make_transient<\/span>(<span class=\"hljs-selector-tag\">order3_items<\/span>)\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.add_all<\/span>(<span class=\"hljs-selector-attr\">&#91;alfki_order3, order3_items]<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now when you query from the orders table, you&#8217;ll not see the third order as before unless you flush the transaction:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.query<\/span>(<span class=\"hljs-selector-tag\">Order<\/span><span class=\"hljs-selector-class\">.id<\/span>)<span class=\"hljs-selector-class\">.all<\/span>()\n<span class=\"hljs-selector-attr\">&#91;&#91;1,), (2,)]<\/span>\n\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.flush<\/span>()\n\n&gt;&gt;&gt; <span class=\"hljs-selector-tag\">session<\/span><span class=\"hljs-selector-class\">.query<\/span>(<span class=\"hljs-selector-tag\">Order<\/span><span class=\"hljs-selector-class\">.id<\/span>)<span class=\"hljs-selector-class\">.all<\/span>()\n<span class=\"hljs-selector-attr\">&#91;(1,), (2,), (3,)]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Nothing is changed in the database yet unless you <a href=\"https:\/\/docs.sqlalchemy.org\/en\/20\/orm\/session_api.html#sqlalchemy.orm.Session.commit\" target=\"_blank\" rel=\"noopener\">commit the current transaction<\/a> using <code>session.commit()<\/code>. This commit function flushes the pending changes, which means it <em>always<\/em> calls the <code>session.flush()<\/code>.<\/p>\n\n\n<div\n\tclass=\"sandbox-embed responsive-embed  sandbox-embed--full-width\"\n\tstyle=\"padding-top: 125%\"\ndata-block-name=\"coderpad-sandbox-embed\">\n\t<iframe src=\"https:\/\/embed.coderpad.io\/sandbox?question_id=233223&#038;use_question_button\" width=\"640\" height=\"800\" loading=\"lazy\" aria-label=\"Try out the CoderPad sandbox\"><\/iframe>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>In applications like CRMs or ordering apps, transactions play an important role in the database. This tutorial has covered a practical guide to how transactions work in SQLAlchemy ORM.<\/p>\n\n\n\n<p>You started with building the data model of an inventory app and created the session instance. You inserted practical data and implemented the logic you needed for implementing transactions. You saw how to roll back a transaction when there is an exception like <code>IntergrityError<\/code>. And you finally learned the difference between commit and flush.<\/p>\n\n\n\n<p><em>I\u2019m Ezz. I\u2019m an AWS Certified Machine Learning Specialist and a Data Platform Engineer. I help SaaS companies rank on Google. Check out my&nbsp;<a href=\"https:\/\/ezzeddinabdullah.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">website<\/a>&nbsp;for more.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Database transactions are sequences of multiple operations performed on a database. In this blog post, Ezz walks through understanding transactions in SQLAlchemy.<\/p>\n","protected":false},"author":1,"featured_media":22176,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[],"persona":[29],"blog-programming-language":[67,37],"keyword-cluster":[],"class_list":["post-21902","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/21902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/comments?post=21902"}],"version-history":[{"count":118,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/21902\/revisions"}],"predecessor-version":[{"id":32644,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/21902\/revisions\/32644"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media\/22176"}],"wp:attachment":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media?parent=21902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/categories?post=21902"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/tags?post=21902"},{"taxonomy":"persona","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/persona?post=21902"},{"taxonomy":"blog-programming-language","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/blog-programming-language?post=21902"},{"taxonomy":"keyword-cluster","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/keyword-cluster?post=21902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}