JPA 에서 SequentialUUID 를 사용하려면 우선 Utils 에 SequentialUUID 생성 하는 함수를 생성한다.
const val SEQUENTIAL_UUID_SIZE = 32
fun creteSequentialUUID(): String {
val uuidParts = Generators.timeBasedGenerator().generate().toString().split("-")
return StringBuffer(SEQUENTIAL_UUID_SIZE).apply {
append(uuidParts[2])
append(uuidParts[1])
append(uuidParts[0])
append(uuidParts[3])
append(uuidParts[4])
}.toString()
}
환경 정보
- Kotlin 1.7.22
- Spring Boot 3.0.2
- PostgreSQL 16 - Local with Podman
1. Entity 에서 직접 ID 에 주입 하는 방식
- Entity Class
import com.example.kotlinplayground.common.utils.creteSequentialUUID
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import java.time.LocalDateTime
@Entity
@Table(name = "table_uuid")
class TableUUID(
@Id
@Column(columnDefinition = "varchar(32)")
var id: String = creteSequentialUUID(),
val name: String,
val email: String,
val password: String,
val createdAt: LocalDateTime = LocalDateTime.now(),
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is TableUUID) return false
if (id != other.id) return false
return true }
override fun hashCode(): Int {
return id.hashCode()
}
}
- Repository Class
import com.example.kotlinplayground.domain.tableUUID.TableUUID
import org.springframework.data.jpa.repository.JpaRepository
interface TableUUIDRepository : JpaRepository<TableUUID, String>,
- TableUUIDRepositoryTest - kotest 의 DescribeSpec 사용
@SpringBootTest
@ActiveProfiles("local")
@Transactional
class TableUUIDRepositoryTest @Autowired constructor(
private val tableUUIDRepository: TableUUIDRepository
) : DescribeSpec({
describe("tableUUIDRepository") {
context("tableUUID 를 생성해서 저장하면") {
val tableUUID = tableUUIDRepository.save(createTableUUID())
it("count 1이 된다.") {
println("tableUUID.id = ${tableUUID.id}")
tableUUIDRepository.count() shouldBeGreaterThanOrEqual 1
}
it("id 의 길이는 32 이다") {
println("tableUUID.id = ${tableUUID.id}")
tableUUID.id.length shouldBe 32
}
}
}
)}
2. Entity 에서 @GeneratedValue 처럼 Annotation 에서 주입 하는 방식
- IdentifierGenerator 의 구현체를 추가
- SequentialUUIDGenerator 이름의 class 로 생성
import com.example.kotlinplayground.common.utils.creteSequentialUUID
import org.hibernate.engine.spi.SharedSessionContractImplementor
import org.hibernate.id.IdentifierGenerator
import java.io.Serializable
class SequentialUUIDGenerator : IdentifierGenerator {
override fun generate(session: SharedSessionContractImplementor, entity: Any): Serializable {
return creteSequentialUUID()
}
}
- Entity Class
- GeneratedValue Annotation 의 generator 이름을 정의 해줍니다. 이름은 임의로 해주셔도 됩니다.(ex. sequential-uuid)
- GenericGenerator Annotation 에서 name 와 strategy 항목 기입
- GeneratedValue 의 generator 값이랑 동일하게 기입
- 추가 할 Generator 의 Class 가 위치하는 주소
Intellij 에서의 class 위치 복사하기
- 복사하려는 class 우클릭 -> Copy Path / Reference
- Copy Reference 클릭
import jakarta.persistence.*
import org.hibernate.annotations.GenericGenerator
import java.time.LocalDateTime
@Entity
@Table(name = "table_uuid_annotation")
class TableUUIDAnnotation(
@Id
@GeneratedValue(generator = "sequential-uuid")
@GenericGenerator(name = "sequential-uuid",
strategy = "com.example.kotlinplayground.common.domain.SequentialUUIDGenerator"
)
@Column(columnDefinition = "varchar(36)")
val id: String = "",
val name: String,
val email: String,
val password: String,
val createdAt: LocalDateTime = LocalDateTime.now(),
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is TableUUIDAnnotation) return false
if (id != other.id) return false
return true }
override fun hashCode(): Int {
return id.hashCode()
}
}
- TableUUIDAnnotationRepository Class
import com.example.kotlinplayground.domain.tableUUIDAnnotation.TableUUIDAnnotation
import org.springframework.data.jpa.repository.JpaRepository
interface TableUUIDAnnotationRepository : JpaRepository<TableUUIDAnnotation, String>,
- TableUUIDAnnotationRepositoryTest - kotest 의 DescribeSpec 사용
@SpringBootTest
@ActiveProfiles("local")
@Transactional
@Commit
class TableUUIDAnnotationRepositoryTest @Autowired constructor(
private val tableUUIDAnnotationRepository: TableUUIDAnnotationRepository,
) : DescribeSpec({
extension(SpringExtension)
describe("tableUUIDAnnotationRepository") {
context("tableUUIDAnnotationRepository 를 생성해서 저장하면") {
val tableUUIDAnnotation = tableUUIDAnnotationRepository.save(createTableUUIDAnnotation())
it("count 1이 된다.") {
println("tableUUID.id = ${tableUUIDAnnotation.id}")
tableUUIDAnnotationRepository.count() shouldBeGreaterThanOrEqual 1
}
it("id 의 길이는 32 이다") {
println("tableUUID.id = ${tableUUIDAnnotation.id}")
tableUUIDAnnotation.id.length shouldBe 32
}
}
}
})
자세한 코드는 링크 에 있습니다!
출처
반응형
'Spring > Spring Data' 카테고리의 다른 글
Spring JPA 예약어 컬럼 이슈 (0) | 2023.02.06 |
---|---|
Spring 프로젝트 DataSource 없이 실행 (0) | 2023.02.06 |