I have a spring web application with Spring Boot(v2.3.3) and Spring Data. I have a table assessment that contains the following columns:
Id
Name
Address
Version
My use case is any changes of name and address in the table assessment a new row should be created and the version incremented with the same id.
So basically only when either the address or name are updated a new record should be inserted in the assessment table an example is shown below:
Existing record:
Id - 23
Name - John
Address - Southend
Version - 1
For example, the name has been updated to Ryan and there should be two rows as follows:
Id - 23
Name - John
Address - Southend
Version - 1
Id - 23
Name - Ryan
Address - Southend
Version - 2
So basically any changes in the name and address should be audited in assessment table and the version should be incremented.
I have seen hibernate envers for auditing but a new audit table needs to be created and therefore I cannot insert it in the assessment table and also I don't know how to generate the version number.
I can write the code programmatically to achieve this but is there any other available auditing tool that I can achieve it please?
Thanks in advance
I am not sure what yours expectations.
Why you want to use some tool ? Like envers.
The problem is connected with automation and DB so first think is trigger.
Mabye the simplest and best way is write just PostUpdateEventListener.
public class VersionUpdateEventListener
implements PostUpdateEventListener {
#Override
public void onPostUpdate(
PostUpdateEvent event) {
/*
1. getOldState() and getState()
2. check updated values
3. update version +1 or not
*/
}
...
Or use hibernate #PostUpdate annotation.
I'm sure you'll figure it out an find details in docs/google.
Your main entity should have columns Id, Name, Address (not version). And you should put #Audit over entity. After that, you should generate database table scripts (see, for example, method main in the org.hibernate.tool.hbm2ddl.SchemaExport).
You will see in script the main and archive table (with the _aud suffix). It will contain the Id,Name, Address, rev. the rev field is your version. When you change the name to Ryan in the main entity and commit, envers automatically adds a new entry to the archive table.
If trigger is supported, try trigger, as it will cover cases updated directly from DB.
Related
I'm using Spring JPA to persist data in my application. I also use Hibernate Envers to create a history for every record I enter into my core table. I would like to get the revision immediately after the write transaction, and show the user what revision was created for the change(s) s/he just made.
In other words:
Step 1: entity -- persisted --> entity table -- envers --> audit table
Step 2: return me the audit version just created
I have taken the approach of persisting the data first, and then retrieve the latest rev info from the audit table in a separate call. This will eventually be inconsistent as the number of users increases.
MyEntity mySavedEntity = myEntityRepository.save(myEntity);
AuditReader reader = AuditReaderFactory.get(entityManager);
List<Number> revisions = reader.getRevisions(MyEntity .class, mySavedEntity.getId());
// ... get the latest revision and pass it back to the user ...
How do I attack this problem? - Thank you
You can make Envers log the version column of your entities by setting org.hibernate.envers.do_not_audit_optimistic_locking_field to false
Then use that column and the value of the version attribute of the entity after the transaction for retrieving the revision.
Maybe you can use the ValidityAuditStrategy, you can check it here, this will let you know your last valid entry and in this case get the last revision.
Do we still have to map All tables to Entity Class in a Spring Hibernate Project ?
I have couple Tables :
- Quote (Transaction)
- NextNumber
- Branch (Master)
e.g :
I want to create a numbering like 'QF18-4238/BHP.SI/ISD', this numbering will saved in Quote Table.
For some Reason:
The Number '4238' -> will also saved in NextNumber Table.
The '/BHP.SI/ISD' -> will lookup from Branch Table depending on whos LoggedIn.
If Login as **A** the result will **'/BHP.TMI/MM'**
else if **B** the result will **''/BHP.SI/ISD**
Is it possible to just create one Entity Class ?
please enlighten me
Database Model:
I am following https://www.javatpoint.com/crud-in-servlet
to create an CRUD application in servlets and mysql.
Each user inputs his information in a webpage and submit to the web server, which then invokes a servlet SaveServlet to save the information as a record in a database table. The database table however has an additional "id".
SaveServlet.java doesn't create an id for each record. So I was wondering how to create an id for each record?
Thanks.
If you are using jpa/hibernate then your entity must be having the #Id annotation on the record id field (you dont need to set it, it will be done automatically based on you Id generation mechanism defined in the entity class and database schema).
if you are using plain jdbc for persisting records then you need to check the database how primary key is defined. for oracle you can your sequence.nextvalue to set the primary key.
Question, am currently using hibernate and I was wondering if there was any way to get the value of a lazy loaded entities id without hitting the DB again? For example we currently have an entity called group that has a ManyToOne relationship with another entity Organization.
when we call a simple repository method
groupsRepository.findByUser(id) it returns a list of groups based on given user. The query looks like this
select
groups0_.PersonId as PersonId1_118_1_,
groups0_.GroupId as GroupId2_8_1_,
groups1_.GroupID as GroupID1_74_0_,
groups1_.CreatedAt as CreatedA2_74_0_,
groups1_.CreatedBy as CreatedB3_74_0_,
groups1_.Description as Descript4_74_0_,
groups1_.Name as Name5_74_0_,
groups1_.OrganizationID as Organiza9_74_0_,
groups1_.Role as Role6_74_0_,
groups1_.Status as Status10_74_0_,
groups1_.TouchedAt as TouchedA7_74_0_,
groups1_.TouchedBy as TouchedB8_74_0_
from
Groupsofpeople groups0_
inner join
groups groups1_
on groups0_.GroupId=groups1_.GroupID
where
groups0_.PersonId=?
Later on I need to see if the groups org is equal to another org which I do by comparing the OrganizaitonId's, a value that has already been fetched from the db. But every time I do this I have fetch the org from the db, is there anyway to prevent that so that the org attached to group will be prepopulated with it's id since it is already being fetched anyway? Or is this just a concession I have to make if I am using hibernate?
I would like to know if it's posible to change the insert and update attributes of a property defined in the mapping of a Class.
This is because in one scenario I need to update a property (or properties), but not in another, it's posible?
Thanks in advance
EDIT: Lets say that I've the Class User(with name, surname and loginDate), when the user logs into the app, I need to update only loginDate. But the administrator of the system must be able to edit the name and the surname of the User.
The only other solution that ocurrs to me is to use HQL for a Update (or in the worst case SQL), but I want if it's posible to modify that attributes.
EDIT 2: after reading Java persistence with hibernate and some forum threads I found that once the sessionFactory is created the mappings are immutables, and though You can change the properties programmatically, You need to create a new sessionFactory
// this is what the login screen calls
void updateLoginDate(Date date)
{
User user = session.get(User.class);
user.setDate(date);
session.Flush();
}
and in the mapping you could specify dynamicUpdate = true on the class so that the generated sql only updates columns which have changed