这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions persistence-modules/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
<module>hibernate-annotations-2</module>
<module>hibernate-reactive</module>
<module>my-sql</module>
<module>spring-data-envers</module>
</modules>

<properties>
Expand Down
61 changes: 61 additions & 0 deletions persistence-modules/spring-data-envers/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-envers</artifactId>
<name>spring-data-envers</name>

<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-3</relativePath>
</parent>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
</exclusion>
</exclusions>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.baeldung.envers.customrevision;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CustomAuditApplication {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.baeldung.envers.customrevision.domain;

import com.baeldung.envers.customrevision.service.CustomRevisionListener;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import lombok.*;
import org.hibernate.envers.DefaultRevisionEntity;
import org.hibernate.envers.RevisionEntity;

@Entity
@RevisionEntity
@EqualsAndHashCode(callSuper = true)
@Getter
@Setter
@NoArgsConstructor
@EntityListeners(CustomRevisionListener.class)
public class CustomRevisionEntity extends DefaultRevisionEntity {

private String remoteHost;
private String remoteUser;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.baeldung.envers.customrevision.domain;

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.envers.Audited;

import java.util.List;

@Entity
@Audited
@Data
public class Owner {
@Id
@GeneratedValue
private Long id;

@Column(nullable = false)
private String name;

@OneToMany(fetch = FetchType.EAGER)
private List<Pet> pets;

public static Owner forName(String name ) {

var owner = new Owner();
owner.setName(name);
return owner;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.baeldung.envers.customrevision.domain;

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.envers.Audited;

import java.time.LocalDate;
import java.util.UUID;

@Entity
@Audited
@Data
public class Pet {
@Id
@GeneratedValue
private Long id;

@Column(unique = true, nullable = false)
private UUID uuid;

private String name;

// A null ownes implies the pet is available for adoption
@ManyToOne
@JoinColumn(name = "owner_id", nullable = true)
private Owner owner;

@ManyToOne
@JoinColumn(name = "species_id")
private Species species;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.baeldung.envers.customrevision.domain;

import org.springframework.data.history.RevisionMetadata;

import java.time.Instant;
import java.util.UUID;

public record PetHistoryEntry(
Instant eventDate,
RevisionMetadata.RevisionType revisionType,
UUID petUuid,
String speciesName,
String petName,
String ownerName,
String remoteHost,
String remoteUser
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.baeldung.envers.customrevision.domain;

import org.springframework.data.history.RevisionMetadata;

import java.time.Instant;
import java.util.UUID;

public record PetLogInfo(
Instant eventDate,
RevisionMetadata.RevisionType revisionType,
UUID petUuid,
String speciesName,
String petName,
String ownerName
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.baeldung.envers.customrevision.domain;

import jakarta.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.envers.Audited;

@Entity
@Audited
@Data
@NoArgsConstructor
public class Species {
@Id
@GeneratedValue
private Long id;

@Column(unique = true)
private String name;

public static Species forName(String name) {
var s = new Species();
s.setName(name);
return s;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.baeldung.envers.customrevision.repository;

import com.baeldung.envers.customrevision.domain.Owner;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface OwnerRepository extends JpaRepository<Owner,Long> {
Optional<Owner> findByName(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.baeldung.envers.customrevision.repository;

import com.baeldung.envers.customrevision.domain.Pet;
import com.baeldung.envers.customrevision.domain.Species;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.history.RevisionRepository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface PetRepository extends JpaRepository<Pet,Long>, RevisionRepository<Pet,Long,Long> {
List<Pet> findPetsByOwnerNullAndSpecies(Species species);
Optional<Pet> findPetByUuid(UUID uuid);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.baeldung.envers.customrevision.repository;

import com.baeldung.envers.customrevision.domain.Species;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface SpeciesRepository extends JpaRepository<Species,Long> {

Optional<Species> findByName(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.baeldung.envers.customrevision.service;


import com.baeldung.envers.customrevision.domain.CustomRevisionEntity;
import com.baeldung.envers.customrevision.domain.Pet;
import com.baeldung.envers.customrevision.domain.PetHistoryEntry;
import com.baeldung.envers.customrevision.repository.OwnerRepository;
import com.baeldung.envers.customrevision.repository.PetRepository;
import com.baeldung.envers.customrevision.repository.SpeciesRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class AdoptionService {

private final OwnerRepository ownersRepo;
private final PetRepository petsRepo;
private final SpeciesRepository speciesRepo;

/**
* Register a new pet for adoption. Initially, this pet will have no name or owner.
* @param speciesName
* @return The assigned UUID for this pet
*/
public UUID registerForAdoption( String speciesName) {

var species = speciesRepo.findByName(speciesName)
.orElseThrow(() -> new IllegalArgumentException("Unknown Species: " + speciesName));

var pet = new Pet();
pet.setSpecies(species);
pet.setUuid(UUID.randomUUID());
petsRepo.save(pet);
return pet.getUuid();
}


public List<Pet> findPetsForAdoption(String speciesName) {
var species = speciesRepo.findByName(speciesName)
.orElseThrow(() -> new IllegalArgumentException("Unknown Species: " + speciesName));

return petsRepo.findPetsByOwnerNullAndSpecies(species);
}

public Pet adoptPet(UUID petUuid, String ownerName, String petName) {

var newOwner = ownersRepo.findByName(ownerName)
.orElseThrow(() -> new IllegalArgumentException("Unknown owner"));

var pet = petsRepo.findPetByUuid(petUuid)
.orElseThrow(() -> new IllegalArgumentException("Unknown pet"));

if ( pet.getOwner() != null) {
throw new IllegalArgumentException("Pet already adopted");
}

pet.setOwner(newOwner);
pet.setName(petName);
petsRepo.save(pet);
return pet;
}

public Pet returnPet(UUID petUuid) {
var pet = petsRepo.findPetByUuid(petUuid)
.orElseThrow(() -> new IllegalArgumentException("Unknown pet"));

pet.setOwner(null);
petsRepo.save(pet);
return pet;
}


public List<PetHistoryEntry> listPetHistory(UUID petUuid) {

var pet = petsRepo.findPetByUuid(petUuid)
.orElseThrow(() -> new IllegalArgumentException("No pet with UUID '" + petUuid + "' found"));

return petsRepo.findRevisions(pet.getId()).stream()
.map(r -> {
CustomRevisionEntity rev = r.getMetadata().getDelegate();
return new PetHistoryEntry(r.getRequiredRevisionInstant(),
r.getMetadata().getRevisionType(),
r.getEntity().getUuid(),
r.getEntity().getSpecies().getName(),
r.getEntity().getName(),
r.getEntity().getOwner() != null ? r.getEntity().getOwner().getName() : null,
rev.getRemoteHost(),
rev.getRemoteUser());
})
.toList();

}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.baeldung.envers.customrevision.service;

import com.baeldung.envers.customrevision.domain.CustomRevisionEntity;
import jakarta.persistence.PrePersist;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.function.Supplier;

@Component
@RequiredArgsConstructor
public class CustomRevisionListener {

private final Supplier<Optional<RequestInfo>> requestInfoSupplier;

@PrePersist
private void onPersist(CustomRevisionEntity entity) {

var info = requestInfoSupplier.get();
if ( info.isEmpty()) {
return;
}

entity.setRemoteHost(info.get().remoteHost());
entity.setRemoteUser(info.get().remoteUser());

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.baeldung.envers.customrevision.service;

public record RequestInfo(String remoteHost, String remoteUser) {
}
Loading