Spring hibernate envers is not saving the updated values - spring

Got an issue with Hibernate Envers. I have an entity that is being created and followed by an update in the integration test and envers has created 2 audit entities corresponding to insert and the update but the update entry is same as insert. The updated value is not reflected while the original entity reflects the updated value. No help googling.
Added spring data envers in the build and added the Audited annotation as required
implementation('org.springframework.data:spring-data-envers')
#Audited
public class EmployeeEntity
#Id
#Column(name = "ID", updatable = false, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonIgnore
private final Long id;
#Column(name = "TYPE")
private String type;
#Column(name = "created_by", nullable = true, updatable = false)
#CreatedBy
private String createdBy;
.... few more fields. In the integration test the type filed is updated and the actual employee table has the updated value however the employee_AUD has the same value as that of insert audit entry

Related

JPA Hibernate Problem for One to One Relationship with Embedded ID

I am struggling with the following problem that I've been trying to solve. After checking solutions on StackOverflow and articles on Baeldung I still get different JPA errors when trying to map the following ONE-TO-ONE relationship between 2 Oracle SQL tables with composite PK in a SpringBoot application:
MASTER
ID
VERSION
1
2022.1
Constraint:
PK_MASTER PRIMARY KEY(ID, VERSION)
MASTER_DETAILS
MASTER_ID
VERSION
DETAILS
1
2022.1
details
Constraint:
PK_MASTER_DETAILS PRIMARY KEY(MASTER_ID, VERSION)
FK_MASTER_DETAILS FOREIGN KEY(MASTER_ID, VERSION) REFERENCES MASTER(ID, VERSION)
After some failures in trying to map it using the #OneToOne JPA annotation with both classes having #EmbeddedId set on the composite PK, I also installed JPA Buddy to check how it will be generated and that resulted in the following 4 classes:
Master.java
#Getter
#Setter
#Entity
#Table(name = "master")
public class Master {
#EmbeddedId
private MasterId id;
#OneToOne(mappedBy = "master")
private MasterDetails masterDetails;
}
MasterId.java
#Getter
#Setter
#Embeddable
public class MasterId implements Serializable {
private static final long serialVersionUID = 8254837075462858051L;
#Column(name = "id", nullable = false)
private BigDecimal id;
#Lob
#Column(name = "version", nullable = false)
private String version;
}
MasterDetails.java
#Getter
#Setter
#Entity
#Table(name = "master_details")
public class MasterDetails {
#EmbeddedId
private MasterDetailsId id;
#MapsId
#OneToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "master_id", referencedColumnName = "id", nullable = false),
#JoinColumn(name = "version", referencedColumnName = "version", nullable = false)
})
private Master master;
#Lob
#Column(name = "details", nullable = false)
private String details;
}
MasterDetailsId.java
#Getter
#Setter
#Embeddable
public class MasterDetailsId implements Serializable {
private static final long serialVersionUID = -8375336118866998644L;
#Column(name = "master_id", nullable = false)
private BigDecimal masterId;
#Lob
#Column(name = "version", nullable = false)
private String version;
}
When running the SpringBoot application with this JPA structure the run time error received is:
org.hibernate.PropertyNotFoundException: Could not locate field [id] on class [org.project.packages.MasterDetails]
After removing the #MapsId that cause this error the application starts but when trying to insert data in the tables I get the following error:
org.hibernate.id.IdentifierGenerationException: null id generated for:class org.project.packages.MasterDetails
Checking in the H2 test database I noticed that the FK on the Master_Details table was not present, but only the PK was set.
I would appreciate any help in pointing out how this problem can be solved: other annotations required (Cascade/FetchType) or in case there are any changes to be made to the database level (I also tried adding a separate identifier column in the Master_Details table defined as PK and only keep the FK to the Master table). Thanks in advance!
After many tries, I figured out to solve the issue.
I had to use a common key between the two entities and also FetchType.LAZY.
MasterDetails.class
public class MasterDetails {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name="ID", column=#Column(name="MASTER_ID"))
})
private MasterId id;
#OneToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumns({
#JoinColumn(name = "master_id", referencedColumnName = "id", nullable = false),
#JoinColumn(name = "version", referencedColumnName = "version", nullable = false)
})
private Master master;
#Lob
#Column(name = "guidance", nullable = false)
private String guidance;
}
Master.class
public class MasterSheet {
#EmbeddedId
private MasterId id;
#OneToOne(mappedBy = "master", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private MasterDetails masterDetails;
}

Spring Boot Jpa Update- Avoid unnecessary updates of columns & child entities

I have a jpa entity with parent-child relationship(1:n).
Any sort of update on the entity results in jpa trying to update each and every column, even if there is no change in the value. I'm confused about the update behaviour for child enitities, I guess same would be happening with those also.
I went through #DynamicUpdate over entities but I do not know how they behave in case of child-entities.
public class Tutorial extends Auditable<String> implements Serializable {
#Id
#GeneratedValue
private Long id;
private String title;
private string description;
#OneToMany(
fetch = FetchType.LAZY,
mappedBy = "tutorial",
cascade = CascadeType.ALL,
orphanRemoval = true)
private Collection<Modules> Modules = new HashSet<>();
// Getter/Setters
}
How to come up with an approach so that only necessary fields/columns and child entities and their columns are update on each save.

Envers, father not revisioned on delete/create of a child

I'm experiencing a problem with revisions on OneToMany relation tables
I have
#Audited
EntityA {
#Id
Integer id;
#OneToMany(mappedBy = "entityA", cascade = CascadeType.ALL)
private List<EntityB> entityBs;
}
and
#Audited
EntityB {
#Id
Integer id;
#Column(name = "ENTITY_A_ID", nullable = false)
private Long entityAId;
#ManyToOne
#JoinColumn(name = "ENTITY_A_ID", insertable = false, updatable = false)
private EntityA entityA;
}
I want that envers creates a new revision of EntityA everytime I delete or create EntityB.
Reading the docs I understand that org.hibernate.envers.revision_on_collection_change is the right configuration property and is by default set to true.
So I can't understand why I don't see any new revision on EntityA when related EntityB is created or deleted.
I tried to create EntityB stand alone and I tried to create via
entityA.getEntityB().add(entityB)
repository.save(entityA)
but no revision of EntityA was saved
Any suggestion?
Thanks in advance
My configuration
spring boot: 2.4.4
hibernate/envers: 5.4.29
jdk 11

How to manually setID for new row? Disable autoincrement. Spring

I have that entity:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "schema_id")
private Integer id;
#Column(name = "schema_name")
private String schemaName;
#Nationalized
#Lob
#Column(name = "schema_ERD")
private String schemaERD;
#ManyToOne
#JoinColumn(name = "user_idFK")
private Users users;
... getters setters
I am adding new rows like that:
Schemas schemas = new Schemas();
schemas.setSchemaERD(...);
schemas.setSchemaName(...);
schemas.setUsers(...;
schemasRepository.save(schemas);
Everything works but my ID is autoincremented. I have reason to disable that.
Is this possible to do something like that? --->
Schemas schemas = new Schemas();
schemas.setId(100);
schemas.setSchemaERD(...);
schemas.setSchemaName(...);
schemas.setUsers(...;
schemasRepository.save(schemas);
I am all time getting erros: about nulls or something else. In some ways i am not getting error but my row will be added with autoincremented id...
Can someone help? :(

Could not fetch the SequenceInformation from the database ERROR but still everything works

I've created user and userRole tables
user entity
#Entity
#Table(name = "USERS")
public class User {
#Id
#Column(name = "USERNAME", nullable = false, unique = true)
private String username;
#Column(name = "PASSWORD", nullable = false)
private String password;
#Column(name = "ENABLED", nullable = false)
private boolean enabled = true;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.EAGER)
private Set<UserRole> userRole = new HashSet<>();
userRole entity
#Entity
#Table(name = "USER_ROLES", uniqueConstraints = #UniqueConstraint(
columnNames = { "ROLE", "USERNAME" }))
public class UserRole {
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_role_id",
unique = true, nullable = false)
private Integer userRoleId;
#Column(name = "ROLE")
private String role;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "USERNAME")
private User user;
When i launch my app i get an Error and this stack trace:
ERROR JdbcEnvironmentImpl:420 - Could not fetch the SequenceInformation from the database
org.h2.jdbc.JdbcSQLException: Column "start_with" not found [42122-197]
But i don't have any 'start_with' columns. Before my UserRole entity was without userRoleId column and everything worked fine but then i added it to do 'role' column not unique and then this happened. But still everything works fine, i just disturbed by this error, what can be the couse of it?
I suggest checking your Hibernate dialect.
I had a similar error because of a start_value column that Hibernate was looking for in sequences of my PostgresQL database. This field name is a default value in Hibernate's SequenceInformationExtractorLegacyImpl class which has many subclasses, each depending on your precise database server and its version. Hibernate loads the right class according to the dialect you specify.
In my case, I was using the org.hibernate.dialect.PostgreSQLDialect dialect, a (deprecated) class meant to be used with a PostgesQL 8.2 version. I switched to org.hibernate.dialect.PostgreSQL9Dialect since my database was hosted on a PostgresQL 9 server. And the issue was gone.

Resources