I have this main class:
@SpringBootApplication
@EnableScheduling
@ConfigurationPropertiesScan
@EnableJpaAuditing(auditorAwareRef = "auditorAwareImpl")
public class PlanetsApplication {
public static void main(String[] args) {
SpringApplication.run(PlanetsApplication.class, args);
}
}
and
@Component("auditorAwareImpl")
public class AuditorAwareImpl implements AuditorAware<String> {
@NotNull
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of("system");
}
}
and
@Getter
@Setter
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
protected LocalDateTime createdAt;
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedDate
@Column(updatable = false)
protected LocalDateTime updatedAt;
@LastModifiedBy
@Column(updatable = false)
protected String updatedBy;
}
and
@Entity
@Table(name = "t_spotify_playlist", uniqueConstraints =
@UniqueConstraint(columnNames = {"playlistId", "sun", "moon"}))
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class SpotifyPlayList extends BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String playlistId;
@Column(length = 50)
private String sun;
@Column(length = 50)
private String moon;
// Many-to-Many relationship with SpotifyTrack
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "t_playlist_track", // Join table name
joinColumns = @JoinColumn(name = "playlist_id"), // Foreign key for SpotifyPlayListDesc
inverseJoinColumns = @JoinColumn(name = "track_id") // Foreign key for SpotifyTrack
)
private Set<SpotifyTrack> tracks; // Tracks associated with the playlist
}
I save the entity:
SpotifyPlayList spotifyPlayList2 = spotifyPlayListService.findAll().stream().findAny().get();
spotifyPlayList2.setSun(spotifyPlayList2.getSun().toUpperCase());
spotifyPlayListService.save(spotifyPlayList2);
log.info("saved {} ", spotifyPlayList2);
but nothing is auditted in the DB
on the logs:
Hibernate:
update
t_spotify_playlist
set
moon=?,
playlist_id=?,
sun=?
where
id=?
also tried
@Getter
@Setter
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseEntity {
@CreatedDate
@Column
protected LocalDateTime createdAt;
@CreatedBy
@Column(updatable = false)
private String createdBy;
@LastModifiedDate
protected LocalDateTime updatedAt;
@LastModifiedBy
protected String updatedBy;
}
with the same result
These two fields in BaseEntity
should not have updatable = false
, and can be written as
@LastModifiedDate
protected LocalDateTime updatedAt;
@LastModifiedBy
protected String updatedBy;
We can verify the behavior in tests
import no.mycompany.auditing.repository.AuditorAwareImpl;
import no.mycompany.auditing.repository.SpotifyPlayList;
import no.mycompany.auditing.repository.SpotifyPlayListRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import static org.junit.jupiter.api.Assertions.*;
@ActiveProfiles("test") // use settings from application-test.yml
@DataJpaTest
@Import(AuditorAwareImpl.class)
class SpotifyPlayListRepositoryTests {
@Autowired
TestEntityManager entityManager;
@Autowired
SpotifyPlayListRepository sut;
@TestConfiguration
static class MySQLTestContainerConfiguration {
@Bean
@ServiceConnection
MySQLContainer<?> mysqlContainer() {
return new MySQLContainer<>(DockerImageName.parse("mysql:latest"));
}
}
@Test
void saveNew_givenValidPlayList_expectAllAuditAwareColumnsToBePopulated() {
var savedPlayList = sut.save(createValidPlayListInTest());
// assert that all auditor aware fields are populated
assertNotNull(savedPlayList.getCreatedAt());
assertEquals("system", savedPlayList.getCreatedBy());
assertNotNull(savedPlayList.getUpdatedAt());
assertEquals("system", savedPlayList.getUpdatedBy());
}
@Test
void updateExisting_givenExistingPlayListInDb_expectOnlyLastModifiedColsToBeUpdated() {
// emulate existing record in db
var existingPlayListInDb = entityManager.persist(createValidPlayListInTest());
var originalUpdateAt = existingPlayListInDb.getUpdatedAt();
// get and update the existing record
var playListToUpdate = sut.findById(existingPlayListInDb.getId()).orElseThrow();
playListToUpdate.setPlaylistId("~newPlaylistId~");
sut.save(playListToUpdate);
entityManager.flush(); // see the update statement in console
// assert that updatedAt is updated
var updatedPlayList = entityManager.find(SpotifyPlayList.class, existingPlayListInDb.getId());
assertTrue(updatedPlayList.getUpdatedAt().isAfter(originalUpdateAt));
}
private static SpotifyPlayList createValidPlayListInTest() {
return SpotifyPlayList.builder()
.playlistId("~playlistId~")
.sun("̃~sun~")
.moon("~moon~")
.build();
}
}