I have a webservice that will be persisting and deleting data to a Database. I want to track in the database which usernames touched which rows of the database. In each table there are columns for usernames to be stored (update columns if you will). There are also triggers on the tables that will take a userID for the transaction and update that table with the username and password that attempted to insert. Is there a way in open JPA where I can get the username (which will be passed from the client) and update some kind of JPA object so that when JPA persists data, that user name will be thrown into the table?
Asked
Active
Viewed 469 times
1 Answers
1
One of the cleanest ways is to implement a common "mapped" superclass for your entities and use a method with @PrePersist
annotation to populate the fields.
@MappedSuperclass
public class AuditedEntity {
@Id protected Integer id;
protected String lastUpdatedBy;
// Setters and getters here
@PreUpdate
@PrePersist
public void onChange() {
String user = .... // Do whatever is needed to get the current user
setLastUpdatedBy(user);
}
}
@Entity
public class Employee extends AuditedEntity {
// ....
}
Another option is to use a separate listener:
public interface AuditedEntity {
public static void setLastUpdatedBy(String username);
}
@Entity
@EntityListeners({ MyLogger.class, ... })
public class Employee implements AuditedEntity {
// ...
}
public class MyLogger {
@PreUpdate
@PrePersist
public void onChange(Object o) {
if(o instanceof AuditedEntity) {
String user = .... // Do whatever is needed to get the current user
((AuditedEntity) o).setLastUpdatedBy(user);
}
}
@PostPersist
@PostUpdate
public void logChange(Object o) {
// Log the successful operation
}
}

anttix
- 7,709
- 1
- 24
- 25
-
Is there any way one can set the Sys_Context (using Oracle for example)? I was kind of trying to avoid using a superclass. But if I have to I will. – SoftwareSavant Aug 27 '12 at 20:10
-
You want to steer clear of database specific stuff in your JPA code. You will lose the possibility to change database engine in the future or to use in-memory database for unit tests. – anttix Aug 27 '12 at 20:15
-
You can use listeners if you do not want to mess with the mappedsuperclass (it has it's own downsides). See the updated post on how. – anttix Aug 27 '12 at 20:22
-
Oh and another reason why you do not want to use database contexts (that are tied to a current database connection) is the fact that the connection is shared so updates can come in from multiple users at the same time. So you need to figure out a way to prefix every single insert and update query with a custom SQL command to store user id in the context. – anttix Aug 27 '12 at 20:29