2

I have an already populated SQL database where I would like to add Javers auditing. Is there a way to initialize the jv_snapshot table with the current state of objects prior to running the initial update on a specific object? I find that I am losing the previous state as the jv_snapshot table contains the update state as the initial state. I am running a spring boot app with hibernate/jpa.

MD XF
  • 7,860
  • 7
  • 40
  • 71

3 Answers3

1

Depending on the size of your database it may take hours or days to sync every record with Javers even if those records may never change from the Initial state.

It may not be exactly what you're looking for, but it works for me.

 // UserService.java

 @Autowired
 private Javers javers;
 @Autowired
 private UserRepository userRepository;

 public void updateUser(UserDTO user){

      User existing = userRepository.findOne(user.getId());

      // Initial Commit Assuming This Record is Not Tracked by Javers Yet
      javers.commit("Initial", existing);

      // Update Logic ... 
      existing.setUpdatedTimestamp(LocalDateTime.now());
      userRepository.save(existing);
 }

 public void deleteUser(Long id){

      User existing = userRepository.findOne(id);

      // Initial Commit Assuming This Record is Not Tracked by Javers Yet
      javers.commit("Initial", existing);

      // Delete Logic ...
      userRepository.delete(id);
 }

 // UserRepository.java
 @Repository
 @Transactional
 @JaversSpringDataAuditable
 public interface UserRepository extends JpaRepository<User, Long>{}

With this logic above you will always have the initial state your object was in before an UPDATE or DELETE occurs. In the event of a CREATE the initial state would be captured by Javers automatically.

Hope this helps.

wheeleruniverse
  • 1,511
  • 2
  • 20
  • 37
0

If you are asking about some kind of data migration tools -- JaVers doesn't provide any. What I can suggest is using JaVers API only, also for bulk changes.

Bartek Walacik
  • 3,386
  • 1
  • 9
  • 14
  • Can you clarify what do you mean by "use JaVers API only, also for bulk changes" please? I too would like to persist the initial data state as the "initial" commits for all GlobalIDs, but I don't understand your suggestion. Maybe I misunderstood but it seems it's not possible/supported at the moment, correct? – Acapulco Dec 06 '18 at 04:39
  • 1
    Simply you have 2 options: a) use javers.commit() methods (JaVers API ) b) directly update your database – Bartek Walacik Dec 06 '18 at 08:08
0

Although a bit late probably, I hope this answer helps expand Bartek's suggestion to do a manual javers.commit(), because I had the same problem and the solution turned out to be very easy.

Basically, I created a job that I can call from a particular controller (e.g. InitialSnapshotJobController) that exposes an endpoint like /api/jobs/initialSnapshot, e.g.

@GetMapping("/api/jobs/initialSnapshot")
public JobResult initialSnapshotJob(){...}

This job has references to all the services of the entities I want to persist, e.g.

@Autowired
public InitialSnapshotJobController(Javers javers, FileService fileService, PriceService priceService){
    initialSnapshot();
}

And what in the job I just do a findAll() on each service, iterate over all the items returned, and commit them to JaVers manually, e.g.

public void initialSnapshot(){
    List<File> files = fileService.findAll();
    files.forEach(file ->{
        javers.commit("InitialSnapshotJob", file);
    })
    ...
}

This worked as expected and now I can store any future changes as updates, which allows me to get only what changed from the baseline without setting the JaVers flag for new objects.

You could also modify the job to receive a list of services instead of hard coding them, and then if later on you need to get a snapshot of a new Entity, you can do so for that one only.

Acapulco
  • 3,373
  • 8
  • 38
  • 51
  • Do you know the efficiency of this when dealing with millions of database records? – wheeleruniverse Dec 10 '18 at 14:54
  • Honestly, I have no idea. The project I'm using Javers for has less than 500k records. For a scale of millions, I guess it would be better to get a snapshot by smaller chunks, as it doesn't seem particularly performant to read every single record and then write what's basically a serialized copy plus some metadata. – Acapulco Dec 11 '18 at 02:07