Answer the question
In order to leave comments, you need to log in
ORM and object changes in different places in the code?
Suppose there is some system with a database. There are three entities in this system:
- user (User),
- transaction (Transaction),
- user account (Account).
They are connected in such a way that the user and the transaction refer to the account by the foreign key.
We want to work with this whole thing through some kind of ORM. In my case, this is Django ORM.
Next, let's say we have some account that initially has a balance of 100. We also have a transaction and a user that refer to that account.
Now we do the following:
1. Access the user.account field so that the account object is pulled from the database into one variable: print user.account
2. Access the transaction.account field so that the account object is pulled from the database into another variable:print transaction.account
3. Update the user's account and save:
user.account.balance = 0<br/>
user.account.save()
transaction.account.balance += 100<br/>
transaction.account.save()
Answer the question
In order to leave comments, you need to log in
As I understand it, all code must be executed within a single transaction. In Django, this is done using the transaction (from django.db import transaction) decorator. And operation 3 cannot be executed until, say, operation 4 is completed.
Regarding the second question. In Hibernate, if all operations occur within the same session (Hibernate Session), then transaction.account and user.accout will return the same entity, so you can safely change its fields in different places in the code.
Maybe I don’t understand something, but apparently ActiveRecord is used and a record like user.account.save () should save the data in the database, right? No matter where it is called from, the save method must save the current changes to the object in the database, otherwise why is it needed at all?
For one operation, manipulations with the account in two different places should not be done. The problem is the architecture of the code, it's bad. You just need to look at everything together and refactor
The only correct solution to your problem is to use select for update. And yes, in order to protect yourself from hard-to-find errors, you should add a field with the version. Even if there is no synchronization, then at least transactions will be rolled back. Well, or use the SERIALIZATION isolation level, which will also roll back the transaction.
Also think, do you really need the “Account” entity? In fact, as far as I understand, this is just a cache so that the balance from transactions is not recalculated every time. So treat it like a cache - the same approaches to invalidation, etc. Maybe even recalculating the amount on the account each time will turn out to be ok, are you sure you run into this in terms of speed?
And, of course, there should be only one account update point: either some explicit function, or to create a Transaction to recalculate the value in Account, or (imho badly) to create a Transaction to change Account.
select_for_update is in the junga trunk. For an atomic increase in the field, you can use the F-object (but it's better to recalculate everything in its entirety, again imho).
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question