Panache: Insert or ignore child - quarkus

I want to persist an entity that has a #OneToMany relationship to a child entity. I'm using Quarkus 1.13.1 with Quarkus Panache.
Example
public class User {
private List<Item> items;
#OneToMany(cascade = CascadeType.ALL)
public List<Item> getItems()...
}
If I want to persist a user (user.persist()) with a few items that already exist in the item table, then I get of course a "duplicate key" exception. So far so good.
But I was wondering if there is a descent way to skip/ignore an insert if an item already exists in the table items.
Of course, I could query the database to check if the child value exists, but this seems somehow tedious and bloats the code with data checks, so I was wondering if there was some annotation or other shortcut to handle this.

A persist operation should be used exclusively to create (store) new objects in the database, and makes the Java objects managed by Hibernate until the Session is closed.
It's really important that you know which objects are managed, and which are not, and distinguish wich ones are newly made persistent rather than just represent an existing object in the database.
To this end, it would indeed be better to load the existing Items first; if you know for sure which ones are already existing in the DB you can use a lazy proxy to represent them and put those in the list before persisting the User.
If you don't know which Items already exist in the database, then you should indeed have to query the database first. There is no shortcut for this operation; I guess we could explore some improvements but generally automating such things is tricky.
I would suggest implement the checks explicitly so you have full control over the strategy. It might be a good idea to make Item a cached entity so you can implement safe validations without performance drawbacks.

Related

Referencing object should be updated if referenced object is saved?

Imagine the following situation: We have two database tables, Tenant and House. Tenant references House with a #ManyToOne mapping.
Tenant tenant = tenantRepository.findById(id).orElseThrow();
House house = tenant.getHouse();
house.setPrice(340_000);
house = houseRepository.save(house); // A new instance is returned by the CrudRepository::save() method
// TODO Is this necessary for further use?
tenant.setHouse(house);
// Further use...
tenant.setAge(23);
tenant = tenantRepository.save(tenant); // Otherwise it is saved with the old reference where house's ID can be null?
...
Is it necessary to update the Tenant with the new reference of House?
EDIT: For clarification, you may assume the entities were loaded (therefore, in managed state) immediately before the above code. And because this "transaction" is a part of a Spring #RequestMapping function, the transaction will be implicitly committed in the end of it.
EDIT 2: The question is not whether I should or not save the house at all in the beginning to avoid this situation. It is about understanding better how the objects are managed.
--- But you may tell me also, should I just update everything first, and save in the end, as a common practice?
The critical question is are house and tenant already managed entities?
If yes (because they got loaded in the same transaction that is still running) all the House instances involved are the same and you don't need to set the house in tenant.
But in that case, you don't even need to call save anyway.
If they are detached instances, yes you need to call tenant.setHouse(house);.
Without it, you will get either an exception or overwrite the changes to house, depending on your cascade setting on the relation.
The preferred way to do all this is:
Within a single transaction:
Load the entities
manipulate them as desired
commit the transaction
JPA will track the changes to the entities and flush them to the database before actually committing the database transaction.

Can I commit a portion of an #Transactional sequence?

I have a Spring Boot application, and have a webservice where a user can POST a model of a CollegeCourse instance which includes links between that class and the Students who are taking it. (The data is used to store rows in the association table, since those classes have a many-to-many relationship.) This works fine.
Say the enrollment in the course changes. The User expects to send the same JSON structure to the webservice handling the PUT call. The code took the easy path for updating, first finding and deleting all the existing CollegeCourse-Student links, then saving the new links. (Rather than iterating through the two lists, matching up items.) This part worked also as given.
We then added a uniqueness constraint to the CollegeCourse-Student association table, so that said table could not have a single Student linked to one CollegeCourse multiple times. This crashed and burned. A debugging session revealed the culprit: the delete of the CollegeCourse-Student records did not actually remove them from the database until the transaction completed. Thus, when we tried to add the new links back in, any holdovers from the original POST conflicted with what was already in the database.
The service handling the PUT is preceded by a #Transactional annotation. I tried moving the code to find and delete the associations in a separate method, and tried both #Transactional(propagation=Propagation.REQUIRED) and REQUIRES_NEW, but neither prevented failing the uniqueness constraint. I also added #EnableTransactionManagement to my Application class - same story. Is there a simple solution to my dilemma?
Without knowing exactly what your repository looks like, have you tried to do a manual flush on the entity manager after the deletions?
Something along the lines of
entityManager.flush();
Or, if you're using a Spring Data JPA repository, you should be able to define a flush method in that interface and call it.

Should I extract functionality from this model class into a form class? (ActiveRecord Pattern)

I am in the midst of designing an application following the mvc paradigm. I'm using the sqlalchemy expression language (not the orm), and pyramid if anyone was curious.
So, for a user class, that represents a user on the system, I have several accessor methods for various pieces of data like the avatar_url, name, about, etc. I have a method called getuser which looks up a user in the db(by name or id), retrieves the users row, and encapsulates it with the user class.
However, should I have to make this look-up every-time I create a user class? What if a user is viewing her control panel and wants to change avatars, and sends an xhr; isn't it a waste to have to create a user object, and look up the users row when they wont even be using the data retrieved; but simply want to make a change to subset of the columns? I doubt this lookup is negligible despite indexing because of waiting for i/o correct?
More generally, isn't it inefficient to have to query a database and load all a model class's data to make any change (even small ones)?
I'm thinking I should just create a seperate form class (since every change made is via some form), and have specific form classes inherit them, where these setter methods will be implemented. What do you think?
EX: Class: Form <- Class: Change_password_form <- function: change_usr_pass
I'd really appreciate some advice on creating a proper design;thanks.
SQLAlchemy ORM has some facilities which would simplify your task. It looks like you're having to re-invent quite some wheels already present in the ORM layer: "I have a method called getuser which looks up a user in the db(by name or id), retrieves the users row, and encapsulates it with the user class" - this is what ORM does.
With ORM, you have a Session, which, apart from other things, serves as a cache for ORM objects, so you can avoid loading the same model more than once per transaction. You'll find that you need to load User object to authenticate the request anyway, so not querying the table at all is probably not an option.
You can also configure some attributes to be lazily loaded, so some rarely-needed or bulky properties are only loaded when you access them
You can also configure relationships to be eagerly loaded in a single query, which may save you from doing hundreds of small separate queries. I mean, in your current design, how many queries would the below code initiate:
for user in get_all_users():
print user.get_avatar_uri()
print user.get_name()
print user.get_about()
from your description it sounds like it may require 1 + (num_users*3) queries. With SQLAlchemy ORM you could load everything in a single query.
The conclusion is: fetching a single object from a database by its primary key is a reasonably cheap operation, you should not worry about that unless you're building something the size of facebook. What you should worry about is making hundreds of small separate queries where one larger query would suffice. This is the area where SQLAlchemy ORM is very-very good.
Now, regarding "isn't it a waste to have to create a user object, and look up the users row when they wont even be using the data retrieved; but simply want to make a change to subset of the columns" - I understand you're thinking about something like
class ChangePasswordForm(...):
def _change_password(self, user_id, new_password):
session.execute("UPDATE users ...", user_id, new_password)
def save(self, request):
self._change_password(request['user_id'], request['password'])
versus
class ChangePasswordForm(...):
def save(self, request):
user = getuser(request['user_id'])
user.change_password(request['password'])
The former example will issue just one query, the latter will have to issue a SELECT and build User object, and then to issue an UPDATE. The latter may seem to be "twice more efficient", but in a real application the difference may be negligible. Moreover, often you will need to fetch the object from the database anyway, either to do validation (new password can not be the same as old password), permissions checks (is user Molly allowed to edit the description of Photo #12343?) or logging.
If you think that the difference of doing the extra query is going to be important (millions of users constantly editing their profile pictures) then you probably need to do some profiling and see where the bottlenecks are.
Read up on the SOLID principle, paying particular attention to the S as it answers your question.
Create a single class to perform user existence check, and inject it into any class that requires that functionality.
Also, you need to create a data persistence class to store the user's data, so that the database doesn't have to be queried every time.

how can i update an object/entity that is not completely filled out?

I have an entity with several fields, but on one view i want to only edit one of the fields. for example... I have a user entity, user has, id, name, address, username, pwd, and so on. on one of the views i want to be able to change the pwd(and only the pwd). so the view only knows of the id and sends the pwd. I want to update my entity without loading the rest of the fields(there are many many more) and changing the one pwd field and then saving them ALL back to the database. has anyone tried this. or know where i can look. all help is greatly appreciated.
Thx in advance.
PS
i should have given more detail. im using hibernate, roo is creating my entities. I agree that each view should have its own entity, problem is, im only building controllers, everything was done before. we were finders from the service layer, but we wanted to use some other finders, they seemed to not be accessible through the service layer, the decision was made to blow away the service layer and just interact with the entities directly (through the finders), the UserService.update(user) is no longer an option. i have recently found a User.persist() and a User.merge(), does the merge update all the fields on the object or only the ones that are not null, or if i want one to now be null how would it know the difference?
Which technologies except Spring are you using?
First of all have separate DTOs for every view, stripped only to what's needed. One DTO for id+password, another for address data, etc. Remember that DTOs can inherit from each other, so you can avoid duplication. And never pass business/ORM entities directly to view. It is too risky, leaks in some frameworks might allow users to modify fields which you haven't intended.
After the DTO comes back from the view (most web frameworks work like this) simply load the whole entity and fill only the fields that are present in the DTO.
But it seems like it's the persistence that is troubling you. Assuming you are using Hibernate, you can take advantage of dynamic-update setting:
dynamic-update (optional - defaults to false): specifies that UPDATE SQL should be generated at runtime and can contain only those columns whose values have changed.
In this case you are still loading the whole entity into memory, but Hibernate will generate as small UPDATE as possible, including only modified (dirty) fields.
Another approach is to have separate entities for each use-case/view. So you'll have an entity with only id and password, entity with only address data, etc. All of them are mapped to the same table, but to different subset of columns. This easily becomes a mess and should be treated as a last resort.
See the hibernate reference here
For persist()
persist() makes a transient instance persistent. However, it does not guarantee that the
identifier value will be assigned to the persistent instance immediately, the assignment
might happen at flush time. persist() also guarantees that it will not execute an INSERT
statement if it is called outside of transaction boundaries. This is useful in long-running
conversations with an extended Session/persistence context.
For merge
if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
the persistent instance is returned
the given instance does not become associated with the session, it remains detached
persist() and merge() has nothing to do with the fact that the columns are modified or not .Use dynamic-update as #Tomasz Nurkiewicz has suggested for saving only the modified columns .Use dynamic-insert for inserting not null columns .
Some JPA providers such as EclipseLink support fetch groups. So you can load a partial instance and update it.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/AttributeGroup

How to refresh relational property of a LINQ class?

I have two instances of a program that manipulate same Northwind database.
When I add some records to the database from one of the instances (for example adding some orders to Orders table with a customer foreign key John), I can query these new records from the other instance of the program properly. The problem begins when I want to access these new records using John.Orders. In this situation, the second instance of the program does not see newly added records. What should I do?
The problem you are having is probably related to the time you keep the LINQ to SQL DataContext class alive. It should typically be destroyed after each unit of work you do with it (since it follows the 'unit of work' design pattern), which typically means after each use case / business transaction.
You are probably keeping the DataContext class alive during the entire lifetime of the application. The DataContext class is not suited for this, because it will cache all objects it had once retrieved meaning that your data will get stale.
Create a new DataContext class for every operation or every time the user opens a new form / screen.

Resources