Removing entity in JPA bidirectional OneToMany - jpa-2.0

I have two entities User and Department, There is a bidirectional relation between the two entities (OneToMany and ManyToOne), I manage the relationship in a service class that handles removing and adding users to department in the following:
List<User> originalUserList = userJpaRepository.findAllByDepartment(department);
for (Iterator<User> iterator = originalUserList.iterator(); iterator.hasNext();) {
User user = iterator.next();
if (!department.getDepartmentEmployees().contains(user)) {
user.setDepartment(null);
userJpaRepository.save(user);
}
}
for (User user : department.getDepartmentEmployees()) {
user.setDepartment(department);
userJpaRepository.save(user);
}
Department savedDepartmetn = jpaRepository.save(department);
return savedDepartmetn;
Everything works fine adding and removing users gets reflected to the database, but the only problem is in the second to last line, the isntance savedDepartment will still contain removed Users because hibernate populates its data from a select that happens before the changes done to user is actually flushed to the database. What is the best approach here,
Should I flush before saving the department (and if saving department fails will the transaction be rolled back)
Should I refresh the savedInstance before returning it to the caller
any other Ideas.

There is no need to save anything since you're using attached entities. JPA automatically persists the changes you do to attached entities.
And when you have a bidirectional association, it's your responsibility to make the changes at both sides to ensure that your object model is consistent. If you set user.department to null, then you should also remove the user from department.users.
I don't understand what the above code is doing, but remove the calls to save, and maintain both sides of the association, and everything will be fine.

Related

Autocreate new database rows

My application creates several rows of data per customer per day. Each row is modified as necessary using a form. Several modifications to a row may take place daily. At the end of the day the customer will "commit" the changes, at which point no further changes will be allowed. In each row I have a 'stage' field, stage=1 allows edits, stage=2 is committed, no further changes allows.
How can I update the stage value to 2 on commit?
In my model I have:
#property
def commit_stage(self):
self.stage = 2
self.save()
Is this the correct way to do this? And if so, how to I attach this function to a "commit" button.
I suspect you are confused about what properties do. You should absolutely not attach this sort of functionality to a property. It would be extremely surprising behaviour for something which is supposed to retrieve a value from an instance to instead modify it and save it to the db.
You can of course put this in a standard model method. But it's so trivial there is no point in doing so.
In terms of "attaching it to a button", nothing in Django can be called from the front-end without a URL and a view. You need a view that accepts the ID of the model instance from a POST request, gets the instance and modifies its stage value, then saves it. There is nothing different from the form views you already use.

Make Doctrine2 automatically remove entities from database when no longer in ArrayCollection

We're dealing with a situation where a user is presented with a form to add/remove some simple OneToMany entities of a Parent entity.
After form submission we've replaced the array collection of the parent with a new one based on the form data.
Using cascade={"persist", "remove"} means that any new OneToMany entities are successfully persisted and added to the database when we persist and flush the Parent.
What we would like is for entities which are no longer in the OneToMany ArrayCollection to be automatically removed from the database during the Parent's persist and flush, thereby allowing us to delete the ugly code we wrote to remove them one by one.
Is this possible?

Where to put pre-flush entity state data in Zend where EntityRepository can access it?

I have an Person that is many-to-one with a Family. The system takes in many rows of data with multiple persons at the same time, which may or may not belong to the same families. I don't have the information about families beforehand.
When I process a Person to enter into the system, I check whether I need to add its Family to the database first. I naturally ask about that from FamilyRepository, but even if I've already created and persisted the same Family, the FamilyRepository still doesn't know about this, since it's written to database only at flush().
The solution would be to temporarily add a reference to somewhere during the PrePersist of the newly created Family, and make the FamilyRepository check from that place as well as from the database.
But where should this temporary persisted-but-not-yet-flushed entity reference go, so that I can access it from the entity's repository?
Alternative solutions I don't like:
The code that does the adding (PersonService->insertPersons()) could of course keep track of the persisted entities, but this seems like a non-optimal solution since it is not a general solution and that code would have to be put each place that adds data.
I could just flush after each addition, but I'd prefer not to flush until all the data has been processed.
I could also loop through $entityManager->getUnitOfWork()->getScheduledEntityInsertions(), and find entries from there, but that seems rather like a hack than an actual solution.
I'm not entirely clear on what you're trying to do, but it sounds like you can handle this by manually handling your transactions (assuming you're using the ORM, anyway. Not sure about transaction support in ODM).
By wrapping your whole import in a transaction, you can make incremental flushes so that SELECTs issued by the repository will return the data, but you can still rollback the entire thing if something goes wrong:
<?php
$em->beginTransaction();
$familyRepository = $em->getRepository('Family');
foreach($personData as $p){
$lastname = $p['lastname'];
$person = new Person();
$person->setLastname($lastname);
$family = $familyRepository->findOneByLastname($lastname);
if (! $family){
$family = new Family();
$family->setLastname($lastname);
$em->persist($family);
}
$person->setFamily($family);
$em->persist($person);
$em->flush();
}
$em->commit();

Is it possible to improve the process of instance creation/deletion in Django using querysets?

So I have a list of unique pupils (pupil is the primary_key in an LDAP database, each with an associated teacher, which can be the same for several pupils.
There is a box in an edit form for each teacher's pupils, where a user can add/remove an pupil, and then the database is updated according using the below function. My current function is as follows. (teacher is the teacher associated with the edit page form, and updated_list is a list of the pupils' names what has been submitted and passed to this function)
def update_pupils(teacher, updated_list):
old_pupils = Pupil.objects.filter(teacher=teacher)
for pupils in old_pupils:
if pupil.name not in updated_list:
pupil.delete()
else:
updated_list.remove(pupil.name)
for pupil in updated_list:
if not Pupil.objects.filter(name=name):
new_pupil = pupil(name=name, teacher=teacher)
new_pupil.save()
As you can see the function basically finds what was the old pupil list for the teacher, looks at those and if an instance is not in our new updated_list, deletes it from the database. We then remove those deleted from the updated_list (or at least their names)...meaning the ones left are the newly created ones, which we then iterate over and save.
Now ideally, I would like to access the database as infrequently as possible if that makes sense. So can I do any of the following?
In the initial iteration, can I simply mark those pupils up for deletion and potentially do the deleting and saving together, at a later date? I know I can bulk delete items but can I somehow mark those which I want to delete, without having to access the database which I know can be expensive if the number of deletions is going to be high...and then delete a lot at once?
In the second iteration, is it possible to create the various instances and then save them all in one go? Again, I see in Django 1.4 that you can use bulk_create but then how do you save these? Plus, I'm actually using Django 1.3 :(...
I am kinda assuming that the above steps would actually help with the performance of the function?...But please let me know if that's not the case.
I have of course been reading this https://docs.djangoproject.com/en/1.3/ref/models/querysets/ So I have a list of unique items, each with an associated email address, which can be the same for several items.
First, in this line
if not Pupil.objects.filter(name=name):
It looks like the name variable is undefined no ?
Then here is a shortcut for your code I think:
def update_pupils(teacher, updated_list):
# Step 1 : delete
Pupil.objects.filter(teacher=teacher).exclude(name__in=updated_list).delete() # delete all the not updated objects for this teacher
# Step 2 : update
# either
for name in updated_list:
Pupil.objects.update_or_create(name=name, defaults={teacher:teacher}) # for updated objects, if an object of this name exists, update its teacher, else create a new object with the name from updated_list and the input teacher
# or (but I'm not sure this one will work)
Pupil.objects.update_or_create(name__in=updated_list, defaults={teacher:teacher})
Another solution, if your Pupil object only has those 2 attributes and isn't referenced by a foreign key in another relation, is to delete all the "Pupil" instances of this teacher, and then use a bulk_create.. It allows only 2 access to the DB, but it's ugly
EDIT: in first loop, pupil also is undefined

django save instance between parent and child model class

I came across this problem on form save the data needs to be persisted somewhere then go through a payment process then on success retrieve the data and save to the proper model.
I have seen this done using session, but with some hacky way to persist file uploads when commit=False and it doesn't seem very pythonic
I am thinking if I have a model class A, and have a child class extending A, such as A_Temp
class A(models.Model):
name = models.CharField(max_lenght=25)
image = models.ImageField()
class A_Temp(A):
pass
class AForm(forms.ModelForm):
class Meta:
model = A_Temp
On model form (A_Temp) save, it stores to A_Temp, and when payment successful, it move the instance to the parent model class A.
Here are the questions:
Has anyone done this before?
How to properly move an instance of a child model class to the parent model class?
Edit:
There are other different ways to do it, such as adding extra fields to the table, yes I would've done that if I am using PHP without a ORM framework, but since the ORM is pretty decent in django, I thought that I might trial something different.
Since I am asking here, means I am not convinced myself about this approach as well. What are your thoughts?
As suggested in the question comments, adding an extra field to your model containing payment state may be the easiest approach. Conceptually it's the same object, it's just that the state changes once payment has been made. As you've indicated, you will need logic to purge out items from your database which never proceed through the required states such as payment. This may involve adding both a payment_state and state_change_time field to your model which indicates when the state last changed. If the state is PAYMENT_PENDING for for too long, that record could be purged.
If you take the approach that unpaid items are stored in a different table as you've suggested, you still have to manage that table to determine when it's safe to delete items. For example, if a payment is never processed, when will you delete record from the A_temp table? Also, having a separate table means that you really only have two states possible, paid and unpaid as determine by the table in which the record occurs. Having a single table with a payment_state may be more flexible in that it allows you to extend the state as required. eg. Let's say you decide you need the payment states ITEM_SUBMITTED, AWAITING_PAYMENT, PAYMENT_ACCEPTED, PAYMENT_REJECTED. This could all be implemented with a single state field. If this was implemented as you've described, you'd need a separate table for each state.
Having said all that, if you're still set on having a separate table structure, you can create a function which will copy the values from an instance of A_temp to A. Something like the following may work, but any relationship type fields such as ForeignKey are likely to require special attention.
def copy_A_temp_to_A(a, a_temp):
for field_name in a._meta.fields:
value = getattr(a, field_name)
setattr(a_temp, field_name, value)
When you need to do the move from A_temp to A, you'd have to instantiate an A instance, then call the copy function, save the instance and delete the A_temp instance from the database.