Treat Entity with Id NULL as NEW - javers

To the question "Save Differences with Entity ID" I found the following answer:
"For Entities, Id property cannot be null, so you need to map this class as ValueObject. If so,
Id property is treated as regular property and it not goes to GlobalId of this object."
My question is:
Why can't an entity be treated as NEW if the Id is NULL?
I have an object graph that is fetched from the database, and between two javers commits an entity is added to a list in the graph.
Two commits and in the second commit there is a new entity (Id NULL)
Get the change => exeption because Javers can't create a GlobalId.
I can get arround this by doing EntityManager - persist (creates Id:s), but I would like to avoid doing that. The present code may do a persist later or it just lets the transaction finish.
Because the Id is NULL, the entity is NEW. Would it be possible to generate a unigue temp Id (allow Id = NULL) to be able to create the GlobalId?
In the change list, the entity would be reported as NEW. No need to compare with earlier commits.

You should compare/commit your objects when they are fully initialized so when they have Ids.
An entity without Id can't be handled by JaVers for several reasons:
it can't be compared to other entity/version (diff algorithm is based on GlobalIds)
it can't be queried from JaVersRepository (queries use GlobalIds)
If you are using Hibernate, compare/commit your new objects after Hibernate assigns them Ids from sequences.
Another options:
don't use sequence-generated values as JaVers Id but some business identifiers
if an Entity doesn't have a business identifier you can generate UUID in a constructor and use it as JaVers id (and also database PK if you like)

Related

Saving entity with id value JPA

So, let's say that I have an object A which has a many to many relationship with object B(B is an entity to a config table in the db which means that the values are not insertable nor updateable.
If I want to save an object A with a list of objects B, is it enough if I provide only the ID of the object B or should I do a query with the ID to get the entire object in order for JPA to do the mapping?
Thanks!
If you are using JPA you need the "complete" objects before persisting them. This means that in your case you will need to get all objects B from the database, then set them in the object A that you are trying to persist and then finally save object A.

How to bulk delete from a JPA repository in Spring Data receiving a list filled with one of the properties from my Entity class

I have an Entity that has four properties, (vehicle, unit, date and id). Primary key is the ID.
I want to delete rows from the database based on the vehicle list provided to me via a request body.
How can I take all the lists and use them to delete data from the database at once?
You can create a "delete...By" query in your Entity repository that takes a List of Vehicle as a parameter and deletes all entities that their Vehicle is contained in that List.
Something like this should work:
void deleteAllByVehicle(List<Vehicle> vehicles);
The documentation contains more options:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
you can use JPQL to provide custom query
#Query(delete from Entity e where e.idvehicle = :id)
void deleteByVehicle(#Param("id") int idvehicle);
now you can just pass the id of the Vehicle like that:
deleteByVehicle(vehicle.getId());

when more foreign keys and need to insert is it good to use native #Query instead of JPA managed way

There is a table with 3 foreign keys to three tables.
To do an insert using JPA, is it suggested/performant to
query individual tables(having foreign key relations) and create
respecitve objects and do a .save()
?
or
use native #Query(), with #Transactional and #Modifying?
for making an insert, i am making 3 calls to DB to get respective objects/details and use them for insertion. so total 4 calls.
If i use native Query, i have the id's required(getting from client) i can do it in one query.
so, is it good to do in JPA way or use native query? which is good in view of performance?
If you have the primary keys of the dependencies you can call EntityManager.getReference().
This will return a placeholder that you can use to set as the dependencies in your entity. That way no SQL statement is executed for the dependencies.
From the API Doc:
<T> T getReference(Class<T> entityClass,
Object primaryKey)
Get an instance, whose state may be lazily fetched.
If the requested instance does not exist in the database, the EntityNotFoundException
is thrown when the instance state is first accessed.
(The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called.)
The application should not expect that the instance state will be available upon detachment,
unless it was accessed by the application while the entity manager was open.
Parameters:
entityClass - entity class
primaryKey - primary key
Returns:
the found entity instance
Throws:
IllegalArgumentException - if the first argument does not denote an entity type or the second argument is not a valid type for that entity's primary key or is null
EntityNotFoundException - if the entity state cannot be accessed
https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#getReference-java.lang.Class-java.lang.Object-

Spring data JPA with H2 database not returning non-merged data

I have an entity with created_date (updateable = false) and updated_date fields. I have #PreUpdate method where I change the updated_date value only (not change created_date), and #PrePersist method which sets new created_date and updated_date values. On Persist the created_date and updated_date are rightly persisted and the returned entity has the correct values. When I pass in the entity to merge, it rightly updates the updated_date (#PreUpdate), and I don't pass the created_date in input. In the database the right updated_date value is updated and created_date value is not changed rightly. But the returned entity has the created_date value set to null. Any Ideas why? Shouldn't the merged entity return the full entity loaded from the database?
Thanks
Sam
I think that is inline with the JPA merge javadoc.
Merge - Merges the state of the given entity into the current persistence context and returns the managed instance that the state was merged to.
(With hibernate as persistence provider) Merge starts with loading the data from the database for that entity, then copies detached entities state to the newly loaded entity. Subsequently, at a later point, during the transaction commit phase(or flush) the dirty checking mechanism fires the update query but won't include the fields marked as updatable=false.
So it doesn't attempt to reload the object with the data in the database after the UPDATE.
To trigger reload, you can rely on refresh(...) that will reload the data.
If it is spring-data-jpa it doesn't expose any refresh method, so you need to add it to your repository and and an example can be found here and discussion on this topic in the spring forum here.

entity framework returning only one value but the list size is correct

Entity framework returning only one value but the list size is correct
I have a table that does not have primary id and I need to get or select all the values in it.
What I see is when I do the selection with linq the number of objects is correct but it is the first row over and over.
I am simply doing something like this
List<MyValueType> valuesInDB = myDb.MyValueTypes.ToList();
Problem is I may get thousands of rows (which is correct) but the rows all have the same exact data.
I am using VS 2010 and used the wizard to create my EF object.
The problem is that entity framework is not able to work with entity without a key. So if your table doesn't specify a key, entity framework will infer its own. The key created by EF is composed of all non-nullable non-binary columns.
So if you for example have single non-nullable column in your entity which have only very small set of values (like enum) you will be able to load only single entity "per value". The reason is an inner implementation of the context and the state manager which uses Identity map pattern. When data record is retrieved from database, EF will first check an entity key and tries to find an object with the same key in its internal storage. If an object is found it will use that object instead of data record retrieved (despite of different data). If an object with the key is not found a new object is materialized and added to internal storage.
That is the purpose of Identity map - object with given key should be created only once by each context. Identity map is core pattern in ORM.
I wrote about Identity map also in this question.
I would suggest searching for the word "Warning" in your EDM's designer.cs file. It might tell you if Entity Framework is having any issues with your table.
I really can't comment much in the absence of the table design. I tried replicating your problem but wasn't able to do so. Here is what I did:
Created a table with no primary key but it had a unique key on an ID column. Entity Framework was able to infer a primary key and when I fetched the data, I not only got the correct number of rows but also the corrects data in those rows.
Created a table with no primary key and no unique key. Also there was no column called ID. Entity Framework excluded this table in the EDM that was generated. Consequently I wasn't able to query this table at all.This was displayed as a warning in the EDM designer file.
It would be better if you can share the create script for your table.

Resources