Ran into what I believe is a bug or at least a shortcoming with Javers.
We have two applications that use a shared database.
The first application is responsible for creating the database entities.
The second application is a batch processing application that reads and updates the same entities after performing a long running batch process, eventually updating the entity with the results of that process.
The first application uses the audit log of the entity (provided by Javers) to show the various changes to the entity over time.
Here's the issue:
In the first application the package name for the entity is something like this:
a.b.c.Entity
In the second application the package name is slightly different:
a.b.c.d.Entity
The different package naming was done to follow the naming/package conventions of the two applications.
Otherwise the two mappings of the entities are identical. Both applications are set up to use Javers for audit logging.
We observed that the changes to the entity performed by the batch application were not showing up in the audit log in the main application.
As it turns out, Javers relies on the entity package name to identify the object recorded in the j_snapshot table. So we had two separate audit trails for the same database table: one for a.b.c.Entity and another for a.b.c.d.Entity even though they shared the same collection and id.
We were able resolve the issue by using the same package for the entity in both applications. This works but it seems rather brittle to me.
A similar scenario could arise if for whatever reason the package name of the mapped entity was changed. All history of the original entity would be essentially lost when looking up the audit changes for the newly renamed entity.
Is there a way to configure Javers to avoid this or are we tied to using the package name in the global_id_key and the object's id as an identifier?
As it's said in Javers' docs. You should use #TypeName:
#TypeName("Person")
class Person {
#Id String name
String position
}
https://javers.org/documentation/domain-configuration/#entity
#TypeName — a convenient way to name Entities and Value Objects. We recommend using this annotation for all Entities and Value Objects. Otherwise, Javers uses fully-qualified class names in GlobalIds, which hinders refactoring classes committed to JaversRepository.
Important! All classes with #TypeName should be registered in JaversBuilder using withPackagesToScan(String)
https://javers.org/documentation/domain-configuration/#supported-annotations
Related
My application uses jBPM. In jBPM may be long live processes, in processes may exist some variables.
For example, I have a business process of contract approval. When process started, empty contract created. After contract owner fill common properties, financial people fill theirs field, security theirs, lawyers theirs, and so on. In result, this long process finished and whole contract with all data will be saved into db. And all time before contract was only a process variable with id == null (saved at finish).
But in some other processes variables can be saved multiple times in process, not only at end (saved multiple times).
I need to track changes in process entities and use javers for it.
Process entities are hibernate #Entity, and by default javers treat them as Entity object. But id of contract appears only at the end of process. And I get ENTITY_INSTANCE_WITH_NULL_ID.
I try to compare them as ValueObject:
Javers javers = JaversBuilder.javers()
.registerValueObject(Contract.class)
.build()
In some situations properties of my entities are hibernate proxies. It is if entity saved multiple times in process. If I use .withObjectAccessHook(new HibernateUnproxyObjectAccessHook()) it tries to get whole db, object references, references of references and so on. So, it is not working solution.
How to get difference of my object in all cases? When Id is null, and when objects are proxies? And not select all data from db :)
For my Symfony2 webapp, I have created a data model consisting of 16 entities. Main entities are User and Company. There is another entity: Location.
There is no implemented functionality concerning the Location, so it's unused by now. (Will say: It is defined as a doctrine entity, but not implemented in any controller.)
I recently signed up for a monitoring service (NewRelic), which allows to check for database performance consumption. Funny thing: My Location entity, which I don't use at all, consumes most performance: It has the highest throughput and is the most time consuming entity in my database. (Besides _session, but don't notice that.)
All other entities listed in that monitoring app are entities, that are used in my app.
There are a couple of other entities that are defined but not implemented. And none of those entities are listed in my monitoring app.
May Location be a Symfony2-reserved entity name that - if used - will consume performance? Do you have any other explanations for this behaviour?
I would like to find out how people out there manage the dbml file in a more scalable manner?
Do you have just one DataClasses1.dbml and drag every table into it?
Do you have separate files for separate logical groupings, eg Accounts, HR? If so, how do you visually see the foreign key relationships when one table has links to a table in another dbml file?
Thanks.
Better will be to use one single DBML file for all your tables, so that you can see all your relations i.e Foreign Key etc all together..But its depends upon your requirement totally..
Using Entity Framework (same for linq-to-sql) I like to use separate context classes for distinct parts of the database.
But what is "distinct"?
In most cases everything that is related to the core business of an application is too much interrelated for a separate context to be meaningful. But almost every application has lateral tasks like authorization, translation, auditing and so on. These are good candidates for separate contexts.
There will still be connections to the business logic though. As you probably know, you cannot join classes from separate contexts in a way that the join is translated to SQL. Only in memory. So it is useful to duplicate some entities in several contexts. So, for instance, both the business context and the authorization context will contain User entities. One context should be responsible for maintenance of the entity and the other one(s) should use it read-only.
Edit
By duplication of entities I mean that two (or more) contexts can have an entity that maps to the same table in the database. Like User. If you like, the business context could be for creating and updating users, the authorization context is (for instance) for adding roles to a specific user, without modifying the user itself.
I have a couple of questions about core data model migration.
I have a pretty complex data model with a couple cases of entity inheritance. I was going to make some changes to the data model in a new version and try and setup migration but when it migrated the store I lost some of the data that belonged to an entity that inherited from another entity.
In my case I have a few entities that all inherit from a "Resource" entity. This resource entity has a attribute "name". When I try to migrate the data store all entities that inherit from the "Resource" entity lose their name.
Is their any way to get model migration working for a data model with inheritance? I have already shipped a beta and I need to make a couple of updates to the model but I obviously don't want the users to lose all of their data.
Thanks
Try "playing" on your new model with Column properties > Versioning > Renaming identier, entering the previous field name, which I guess is the same. I doubt that will work with inheritance, but that is worth the try... (That not so documented feature, allowing to keep data across renames, saved me several times).
If that doesn't work, I'm afraid you have to do a "manual migration"... with Model mappings and other things... which is imho a bit complex. See Apple documentation on this topic... I then would suggest to just rollback your changes and forget inheritance, quicker & easier, even if it is less "clean". Or just assume your users will loose some data, at beta stage this is not so important... (Or maybe you can just collect old data in memory/plist file before migrating model an then repopulate)
Good luck! CoreData automatic model migration is great, but take care that it will work only with simple modifications...
Oh, just one another trick, add -com.apple.CoreData.SQLDebug 1 to your app launch arguments, and you will get all sql requests generated by CoreData... That might help you to understand the migration process. (and some other things...)
If I map my Domain objects to linq Entities will I now not be able to track changes when saving my domain objects? So for any change in my model that i wish to make, once I map the object to linq entities for submission to db, all object values will be submitted to the db by linq since it it goes through a mapping first? Or would the object tracking here still be utilized?
Depends on the O/R mapper you're using. You're referring to entity framework which doesn't do any change tracking inside the entity and therefore it needs help from you when you re-attach an entity which previously was fetched from the db (so it knows it's not new).
Here's an article from microsoft about CRUD operations in multi-tiered environments (similiar issues to your Domain mapping scenario).
Check out the Update - With Complete Entities for the way to do change tracking yourself.
There's another technique, where you attach the entity as unmodified, and then .Refresh() with Keep Current Values - replacing the original. This would allow you to Insert/Update/Do Nothing as appropriate at the cost of a database roundtrip.