i've spring and hibernate project in that i configured audit for Table and its working fine but my problem is i want to avoid audit at time of creating new record but while doing updating it should audit below my code
Entity:
#Entity
#Table(name = "building")
#Audited
public class BuildingClass extends CommonTableFields {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "BID")
#JsonProperty
private long id;
#JsonProperty
private String username;
#JsonProperty
private double count;
//getters and setters
}
implementation:
// here i don't want to audit
#Override
public void save(BuildingClass buildingclass) {
repo.save(buildingclass)
}
// here i want to audit
#Override
public void update(BuildingClass buildingclass) {
repo.save(buildingclass)
}
thanks in advance
It is going to depend on what strategy your using for auditing.
The DefaultAuditStrategy should work by simply not registering post-insert event listener. You would do this by registering your own envers integrator that doesn't register that specific event handler.
The ValidityAuditStrategy will be a bit of a problem. The problem here is that this strategy performs a set of update operations internally when a row is modified and those operations expect the initial insert audit row to exist and will fault if it does not.
You could override this strategy with a custom one that disables this check, but understand the check was added to detect data issues with the audit rows rather than using assumptions.
But the key to all this is conditional auditing, see reference documentation for information.
Related
im working in a spring boot project and i have a requirement to save the old object in a specific table before each new save ; this my man entities:
#Entity
#Table(name="demande")
public class Demande {
#Id
private Long id;
// all properties
}
#Entity
#Table(name="demande_log")
public class DemandeLog {
#Id
private Long id;
// all properties
}
what im trying to do is before each demandeRepository.save(demande);
i want to save the old demande object (current row in database) as DemandeLog in my demande_log table.
do you have any idea how using spring data, i know that there is a listener #PrePersist in JPA.. but i want to do it properly.
Regards.
I recommend using Envers. It is easy to set up and gives you a complete change log.
What is the best way to implement soft delete in spring data and on delete that should also trigger hibernate events
There is an example on how to implement soft deletes in the Hibernate ORM documentation:
#SQLDelete(
sql = "UPDATE person SET valid = false WHERE id = ? "
)
public static class Person {
#Id
#GeneratedValue
private Long id;
private String name;
...
}
I have a Spring Boot application using Spring Data REST. I have a domain entity called User with a boolean field isTeacher. This field has been already setup by our DBA in the User table with type bit and a default value of 1:
#Data
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // This Id has been setup as auto generated in DB
#Column(name = "IS_TEACHER")
private boolean isTeacher;
}
And the User repository:
public interface UserRepository extends CrudRepository<User, Long>{
}
I was able to add a new user by giving the below request and POST to http://localhost:8080/users, a new user was created in the DB having isTeacher value 1:
{
"isTeacher" : true
}
However, when I tried to change IS_TEACHER by giving PATCH (or PUT) and this request:
{
"isTeacher" : false
}
The response showed that "isTeacher" is still true and the value didn't get changed in the table either. Can someone please let me know why this is happening?
The issue is due to #Data annotation of lombok is ignoring if you have a field that start with isXx it generates getters and setters to boolean with isTeacher for getters and setTeacher for setters then you are not able to update correctly your property, if you put "teacher" when updating should work but you should solve this by overriding that setter.
#Setter(AccessLevel.NONE) private boolean isTeacher;
public void setIsTeacher(boolean isTeacher) {
this.isTeacher = isTeacher;
}
I have two entities, Books and Comments, in a one to many relationship (one book can have many comments). I want to be able to list books and number of comments about a book. I want it denormalized, meaning the books entity will have a counter that has number of comments for that book, and it will be updated every time a comment is entered (just playing with the concept, no need to discuss about the need of denormalizing here).
I think (correct me if I am wrong) this could be easily done with a trigger in the database (whenever a new comment is created, update a counter in the books table to the corresponding bookId), but for the sake of learning I want to do it through JPA, if it makes sense.
What I have so far: //omitted some annotations, just general info
Boks entity:
#Entity
public class Books {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String author;
private Long numComments;
// getters and setters...
}
Comments entity:
#Entity
public class Comments {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String comment;
private Long authorId;
private Long bookId;
// getters and setters...
}
Books repository: I added here a query to perform the update
/**
* Spring Data JPA repository for the Books entity.
*/
public interface BooksRepository extends JpaRepository<Books,Long> {
#Modifying
#Query("UPDATE Books v SET v.numComments = v.numComments + 1 WHERE v.id = :bookId")
int updateCounter(#Param("bookId")Long bookId);
}
And now the question: What next? I think I can put the update of the Books entity annotating with #PostPersist a method of the entity Comments, but I have been unsuccessful so far. I can imagine something like this:
#PostPersist //This function in the entity Comments
protected void updateBooks() {
//Likely some call to the repository here that updates the count
// in books the info we have from current entity.
}
Any idea on how to do this? Some best practices about this kind of denormalization in JPA? Better to use the database triggers?
spring not managed your entity classes and your idea is possible but you must inject BooksRepository in enttiy class then stay at you get Nullpointerexception because spring not managed enttiy classes,The reason your BooksRepository not initlaized, try also read this post Bean injection inside a JPA #Entity and anotate entity class #Configurable after
try this
#PostPersist
protected void updateBooks(Comments comment) {
int totalComment = BooksRepository.updateCounter(comment.getBookId());
System.out.println(totalComment); // see totalComment in console
}
but good aprroach in service classes after call updateCounter when insert comment
example in your CommendService : when try a insert commend after call your updateCounter
if(comment.getBookId() != null) //Simple Control
{
CommentRepository.save(comment);
BooksRepository.updateCounter(comment.getBookId());
}
There is a problem about generating id while persisting into database.
I added the following code to my jpa entity file, however I'm getting 0 for personid.
#Id
#Column(unique=true, nullable=false, precision=10, name="PERSONID")
#SequenceGenerator(name="appUsersSeq", sequenceName="SEQ_PERSON", allocationSize=1)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "appUsersSeq")
private long personid;
EjbService:
#Stateless
public class EjbService implements EjbServiceRemote {
#PersistenceContext(name = "Project1245")
private EntityManager em;
#Override
public void addTperson(Tperson tp) {
em.persist(tp);
}
}
0 is default value for long type. The id will be set after invoking select query for the related sequence, which commonly is executed when you persist the entity. Are you persisting the entity? In case yes, post the database sequence definition to check it.