Skip to content

Commit 65ca8a9

Browse files
committed
Add auditing support and custom JPA naming strategy
Introduce auditing fields to track entity changes with `AuditFields` and enable auditing in `Application`. Add a custom JPA naming strategy for quoted snake_case formatting. Update `Member` entity and database schema to include audit fields.
1 parent fa29e0c commit 65ca8a9

File tree

9 files changed

+95
-6
lines changed

9 files changed

+95
-6
lines changed

spring-boot/src/main/java/com/mpc/springboot/Application.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
56

7+
@EnableJpaAuditing
68
@SpringBootApplication
79
public class Application {
810

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.mpc.springboot.config.audit;
2+
3+
import org.springframework.data.domain.AuditorAware;
4+
import org.springframework.stereotype.Component;
5+
6+
import java.util.Optional;
7+
8+
@Component
9+
public class SecurityAuditorAware implements AuditorAware<String> {
10+
11+
@Override
12+
public Optional<String> getCurrentAuditor() {
13+
return Optional.of("test-member");
14+
}
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.mpc.springboot.config.persistence.jpa;
2+
3+
import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
4+
import org.hibernate.boot.model.naming.Identifier;
5+
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
6+
7+
public class QuotedCamelCaseToUnderScoresNamingStrategy extends CamelCaseToUnderscoresNamingStrategy {
8+
9+
@Override
10+
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
11+
if (name == null) {
12+
return null;
13+
}
14+
Identifier snakeCaseIdentifier = super.toPhysicalColumnName(name, jdbcEnvironment);
15+
return Identifier.toIdentifier("`" + snakeCaseIdentifier.getText() + "`", snakeCaseIdentifier.isQuoted());
16+
}
17+
18+
@Override
19+
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
20+
if (name == null) {
21+
return null;
22+
}
23+
Identifier snakeCaseIdentifier = super.toPhysicalTableName(name, jdbcEnvironment);
24+
return Identifier.toIdentifier("`" + snakeCaseIdentifier.getText() + "`", snakeCaseIdentifier.isQuoted());
25+
}
26+
}

spring-boot/src/main/java/com/mpc/springboot/member/application/service/MemberService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.mpc.springboot.member.application.service;
22

3+
import jakarta.transaction.Transactional;
4+
35
import org.springframework.stereotype.Service;
46
import com.mpc.springboot.member.domain.entity.Member;
57
import com.mpc.springboot.member.domain.exception.MemberNotFoundException;
@@ -18,6 +20,7 @@ public Member getMemberBy(MemberCode code) {
1820
.orElseThrow(MemberNotFoundException::new);
1921
}
2022

23+
@Transactional
2124
public Member createMember(Member member) {
2225
return memberRepository.save(member);
2326
}

spring-boot/src/main/java/com/mpc/springboot/member/domain/entity/Member.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import jakarta.persistence.*;
44

5+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
56
import com.mpc.springboot.member.domain.vo.MemberCode;
67
import com.mpc.springboot.member.domain.mapping.MemberCodeConverter;
78
import com.mpc.springboot.member.domain.vo.MemberName;
9+
import com.mpc.springboot.shared.domain.AuditFields;
810
import lombok.*;
911

1012
@Getter
11-
@NoArgsConstructor
13+
@EntityListeners(AuditingEntityListener.class)
14+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
1215
@Entity
1316
public class Member {
1417

@@ -22,10 +25,8 @@ public class Member {
2225
@Embedded
2326
private MemberName name;
2427

25-
public Member(MemberCode code, MemberName name) {
26-
this.code = code;
27-
this.name = name;
28-
}
28+
@Embedded
29+
private AuditFields auditFields = new AuditFields();
2930
}
3031

3132

spring-boot/src/main/java/com/mpc/springboot/member/infrastructure/persistence/jpa/repository/MemberJpaRepository.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import java.util.Optional;
44

55
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.stereotype.Repository;
67
import com.mpc.springboot.member.domain.entity.Member;
78
import com.mpc.springboot.member.domain.vo.MemberCode;
89

9-
public interface MemberJpaRepository extends JpaRepository<Member, Long> {
10+
@Repository
11+
public interface MemberJpaRepository extends JpaRepository<Member, Integer> {
1012

1113
Optional<Member> findByCode(MemberCode code);
1214
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.mpc.springboot.shared.domain;
2+
3+
import jakarta.persistence.Column;
4+
import jakarta.persistence.Embeddable;
5+
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
import org.springframework.data.annotation.CreatedBy;
9+
import org.springframework.data.annotation.LastModifiedBy;
10+
import org.springframework.data.annotation.CreatedDate;
11+
import org.springframework.data.annotation.LastModifiedDate;
12+
13+
14+
import java.time.LocalDateTime;
15+
16+
@Getter
17+
@NoArgsConstructor
18+
@Embeddable
19+
public class AuditFields {
20+
21+
@CreatedBy
22+
@Column(updatable = false)
23+
private String createdBy;
24+
25+
@CreatedDate
26+
@Column(updatable = false)
27+
private LocalDateTime createdDateTime;
28+
29+
@LastModifiedBy
30+
private String lastModifiedBy;
31+
32+
@LastModifiedDate
33+
private LocalDateTime lastModifiedDateTime;
34+
}

spring-boot/src/main/resources/application.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ spring:
99
database: mysql
1010
hibernate:
1111
ddl-auto: validate
12+
naming:
13+
physical-strategy: com.mpc.springboot.config.persistence.jpa.QuotedCamelCaseToUnderScoresNamingStrategy
1214
show-sql: true
1315
properties:
1416
hibernate.format_sql: true
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
alter table member add column created_by varchar(320);
2+
alter table member add column last_modified_by varchar(320);
3+
alter table member add column created_date_time timestamp;
4+
alter table member add column last_modified_date_time timestamp;

0 commit comments

Comments
 (0)