Is it possible to link different javers commits and fetch them together using a deep shadow scope or any other way? - javers

I'm looking for a feature in Javers, when creating a snapshot, to link it with other previously created snapshots.
I looked at the commit-deep scope for the shadows, but it is fetching only the snapshots which have the same commit id.
I want something like this:
Entity Employee is linked oneToOne with Entity Address.
I save an address which stores an Address snapshot A1 with commit c1.
Now I save an employee linking to that address which stores an Employee snapshot E1 with commit c2.
I am not able to fetch these two snapshots A1 and E1 together as they are in different commits (c1 and c2).
Is it possible to get this info with the current Javers or do we need to add a feature for this or is this an over-kill?
The feature can be like this:
If I query for shadows of Employees (byInstanceId say) with a new scope (may be like linked-deep scope), it should give me all shadows of the Employee using commit-deep , plus all the linked shadows, in this case, both snapshots E1 and A1
This way, we can track what address the employee had at a point in history.

You can use Deep+ Shadow Scope.
see https://javers.org/documentation/jql-examples/#query-for-shadows
There are four scopes. The wider the scope, the more object shadows are loaded to the resulting graph (and the more database queries are executed). Scopes are defined in the ShadowScope enum.
Shallow — the defult scope — Shadows are created only from snapshots selected directly in the main JQL query.
Child-value-object — JaVers loads all child Value Objects owned by selected Entities. Since 3.7.5, this scope is implicitly enabled for all Shadow queries and can’t be disabled.
Commit-deep — Shadows are created from all snapshots saved in commits touched by the main query.
Deep+ — JaVers tries to restore full object graphs with (possibly) all objects loaded.

Related

Do I need to save both entities when adding a oneToMany relationship?

TL;DR: Is it enough to call repository.save() on the owning entity to persist the relationship or do I need to save both entities?
Let's say I have two entities, A and B and a oneToMany relationship between them. A can have multiple B's, B can have an A. B is the owning side of the relationship (has the foreign key). If I have two, already persisted entities and want to add and persist a relationship between them, then I typically do this:
a.addB(b);
b.setA(a);
bRepository.save(b);
My question is, do I also need to call aRepository.save(a)? Thanks in advance, Googling didn't help me to find the answer.
If as you describe the relationship is owned by B, A didn't change at all as far as JPA is concerned. So it doesn't need to get persisted.
If you have persisted or loaded A and B in the current session, no save at all is technically necessary. JPA keeps track of the entities, note that they are changed and will flush the changes to the database at the end of the transaction.
Good question and assuming that you have already saved the A entity the answer should be that you do NOT need to save the parent A entity again since you have added the child entity B to A's list of children yourself and A is already persisted.
If you ever reload A and all its children you should get the same list as you currently have.
Since it is lazy loaded your query should specifically load the children in the case you want that otherwise you might get into the situation where you assume that A has all its children but you doesn't if you reloaded A from the database without getting them.
In general though I have to question why you are keeping A around in the first place. Caching can be a good thing but your cache should refresh A when its children are updated and should fetch all of A's children if that is what is needed. In that case you don't need to add the new child to A yourself b/c it will be overwritten anyway. Probably doesn't hurt, but why do you want to second guess the cache?
More generally the pattern is simply to save B and be done with it. If your code needs A and all its children it should fetch from the database when needed.
These thoughts do not include JPAs entity cache since I have not attempted to get into very specific detail about that.

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.

Entity Framework and caching - Changes are tracking back to cache

I have some data being pulled in from an Entity model. This contains attributes of items, let's say car parts with max-speed, weight and size. Since there are a lot of parts and the base attributes never change, I've cached all the records.
Depending on the car these parts are used in, these attributes might now be changed, so I setup a new car, copy the values from the cached item "Engine" to the new car object and then add "TurboCharger", which boosts max speed, weight and size of the Engine.
The problem I'm running into is that it seems that the Entity model is still tracking the context back to the cached data. So when weight is increased by the local method, it increases it for all users. I tried adding "MergeOption.NoTracking" to my context as this is supposed to remove all entity tracking, but it still seems to be tracking back. If I turn off the cache, it works fine as it pulls fresh values from the database each time.
If I want to copy a record from my entity model, is there a way I can say "Copy the object but treat it as a standard object with no history of coming from entity" so that once my car has the attributes from an item, it is just a flattened object?
Cheers!
Im not too sure about MergeOption.NoTracking on the whole context and exactly what that does but what you can do as an alternative is to add .AsNoTracking() into your query from the database. This will definitely return a detached object.
Take a look here for some details on AsNoTracking usage : http://blog.staticvoid.co.nz/2012/04/entity-framework-and-asnotracking.html.
The other thing is to make sure you enumerate your collection before you insert to the cache to ensure that you arent acting within the queriable, ie use .ToArray().
The other option is to manually detach the object from the context (using Detach(T entity)).

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 do I delete an entity when removing it from an array controller?

I have an entity (e.g. Employee) in a managed object model that is related to two other entities (e.g. Department and Team). Both relationships are one-to-many (i.e. an Employee must have one Department and one Team, Teams and Departments have many Employees). The two may or may not overlap (e.g. a team might be made up of employees from HR, Accounting & I.T. or it might jut consist of several employees from the one department).
Department <-->> Employee <<--> Team
I have two NSArrayControllers providing data for two NSTableViews, a Department table and a Team table. Employees can move between departments and between teams without any problems but I'm not sure how to delete (fire) the employee.
If I send either of the array controllers a remove message the employee is taken out of the team (for example) but left in the department and the object graph is in an inconsistent state. Even if I call the remove action on both controllers the object is not deleted - it is orphaned and just hangs around in limbo.
Originally I had the Department & Team relationships (of the Employee entity) set to a delete rule of Nullify but even changing one or both to cascade doesn't help.
Do I need to override the remove: action on the array controllers to actually delete the employee or am I missing something really obvious?
The NSArrayController has two different behaviors when you're using Core Data. If it is configured to simply fetch objects directly from the managed object context, it will delete the objects when they are removed.
If you're binding the contentSet to another controller, like it sounds like you are in this case, the default behavior is to simply remove the object from the relationship. If you want to delete it, though, there is a "deletes object on remove" binding option, which will produce the result you want.

Resources