<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Skerdilajd Hoxha</title>
    <description>The latest articles on DEV Community by Skerdilajd Hoxha (@skerdi).</description>
    <link>https://dev.to/skerdi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1067729%2F3e30023f-866d-4fe4-80d3-db0484ebd05d.jpeg</url>
      <title>DEV Community: Skerdilajd Hoxha</title>
      <link>https://dev.to/skerdi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/skerdi"/>
    <language>en</language>
    <item>
      <title>Transactions - difference between SQL, SQLAlchemy and Django ORM</title>
      <dc:creator>Skerdilajd Hoxha</dc:creator>
      <pubDate>Wed, 19 Apr 2023 13:02:40 +0000</pubDate>
      <link>https://dev.to/skerdi/transactions-difference-between-sql-sqlalchemy-and-django-orm-56i0</link>
      <guid>https://dev.to/skerdi/transactions-difference-between-sql-sqlalchemy-and-django-orm-56i0</guid>
      <description>&lt;h2&gt;
  
  
  What’s a transaction?
&lt;/h2&gt;

&lt;p&gt;In computing, a transaction is a set of related tasks treated as a single action. Together the tasks form a logical unit of work in which all of them must succeed or none of them can succeed. If some tasks succeed but at least one fails, then all successful tasks are reversed, returning the system to its original state before the transaction was initiated. In the context of a database, a transaction is used to create, update, or retrieve data.&lt;/p&gt;

&lt;p&gt;A typical case would be a bank transfer. Peter wants to send $100 to Emma. The process would be to decrease Peter’s amount by $100 and increase Emma’s amount by $100.&lt;/p&gt;

&lt;p&gt;Below, we’ll implement this scenario in SQL, SQLAlchemy and Django ORM.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL transaction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START TRANSACTION;  — initialize transaction

-- removing 10 from user id 1
UPDATE users SET amount = amount - 100 WHERE username = 1;

-- adding 10 to user with id 2
UPDATE users SET amount = amount + 100 WHERE username = 2;

-- committing the change (or roll back in case of failure)
COMMIT;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In SQL we have to start a transaction explicitly "&lt;em&gt;START TRANSACTION&lt;/em&gt;". If all queries are successful, it will be committed. Otherwise, it will be rolled back.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQLAlchemy transaction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user_1 = User.query.query.filter(id=1).first()
user_1.amount -= 100

user_1 = User.query.query.filter(id=2).first()
user_1.amount += 100

session.commit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SQLAlchemy is transactional by default. Meaning that we can do a lot of queries and we have to "&lt;em&gt;commit&lt;/em&gt;" only once. So we don’t have to "&lt;em&gt;START TRANSACTION&lt;/em&gt;" like in SQL. The process is the same: if all queries are successful, they will be committed. Otherwise, they will be rolled back. &lt;a href="https://docs.sqlalchemy.org/en/20/orm/session_transaction.html"&gt;SQLAlchemy docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django ORM transaction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with transaction.atomic():
    user_1 = User.objects.get(id=1).update(amount-=100)
    user_2 = User.objects.get(id=2).update(amount+=100)

@transaction.atomic
def transaction_view(request):
    user_1 = User.objects.get(id=1).update(amount-=100)
    user_2 = User.objects.get(id=2).update(amount+=100)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django’s default behavior is to run in auto-commit mode. Each query is immediately committed to the database.&lt;/p&gt;

&lt;p&gt;Django ORM is not transactional by default like SQLAlchemy. Each query is immediately committed to the database. We have to use a context manager "with transaction.atomic()" or a decorator "@transaction.atomic" to start a transaction.&lt;/p&gt;

&lt;p&gt;If we want to have all of the views "http requests" transactional, we can set "&lt;em&gt;atomic_requests&lt;/em&gt;" to &lt;strong&gt;True&lt;/strong&gt; in the configuration of the database. If we want to prevent views from running in a transaction, we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@transaction.non_atomic_requests
def non_atomic_view(request):
    user_1 = User.objects.get(id=1).update(amount-=100)
    user_2 = User.objects.get(id=2).update(amount+=100)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I wouldn’t recommend it. For more, check the &lt;a href="https://docs.djangoproject.com/en/4.2/topics/db/transactions/"&gt;Django docs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>django</category>
      <category>sqlalchemy</category>
      <category>transaction</category>
    </item>
  </channel>
</rss>
