diff --git a/README.md b/README.md index e567104..a674f8f 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,9 @@ ## common-spring Набор утилит, структур данных для `spring`, без привязки к доп. модулям, таким как `jpa` и `web` + +## common-spring-jpa + +* `models.*` - базовые `Entity` +* `repositories` - утилиты и доп. интерфейсы для репозиториев +* `EnableJpaAuditingExtra` - подключение `JpaAuditing` с поддержкой типа `ZoneDateTime` diff --git a/common-spring-jpa/build.gradle.kts b/common-spring-jpa/build.gradle.kts new file mode 100644 index 0000000..cf997f2 --- /dev/null +++ b/common-spring-jpa/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("kotlin") + id("kotlin-spring") + id("maven-publish") +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + + implementation("org.springframework.boot:spring-boot-starter-data-jpa") +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/EnableJpaAuditingExtra.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/EnableJpaAuditingExtra.kt new file mode 100644 index 0000000..4f36b3c --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/EnableJpaAuditingExtra.kt @@ -0,0 +1,8 @@ +package ru.touchin.common.spring.jpa + +import org.springframework.context.annotation.Import +import ru.touchin.common.spring.jpa.configurations.AuditingConfig + +@Suppress("unused") +@Import(value = [AuditingConfig::class]) +annotation class EnableJpaAuditingExtra diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/configurations/AuditingConfig.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/configurations/AuditingConfig.kt new file mode 100644 index 0000000..57c3de8 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/configurations/AuditingConfig.kt @@ -0,0 +1,25 @@ +@file:Suppress("SpringFacetCodeInspection") +package ru.touchin.common.spring.jpa.configurations + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.data.auditing.DateTimeProvider +import org.springframework.data.jpa.repository.config.EnableJpaAuditing +import java.time.ZoneId +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.util.Optional + +@Configuration +@EnableJpaAuditing( + dateTimeProviderRef = "auditingDateTimeProvider", + modifyOnCreate = false, +) +class AuditingConfig { + + @Bean + fun auditingDateTimeProvider(): DateTimeProvider { + return DateTimeProvider { Optional.of(ZonedDateTime.now(ZoneId.from(ZoneOffset.UTC))) } + } + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableEntity.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableEntity.kt new file mode 100644 index 0000000..cfeef4c --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableEntity.kt @@ -0,0 +1,30 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.models + +import org.springframework.data.annotation.CreatedBy +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedBy +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.io.Serializable +import java.time.ZonedDateTime +import javax.persistence.EntityListeners +import javax.persistence.MappedSuperclass + +@EntityListeners(AuditingEntityListener::class) +@MappedSuperclass +abstract class AuditableEntity : Serializable { + + @CreatedDate + lateinit var createdAt: ZonedDateTime + + @CreatedBy + lateinit var createdBy: String + + @LastModifiedDate + var updatedAt: ZonedDateTime? = null + + @LastModifiedBy + var updatedBy: String? = null + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableLongIdEntity.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableLongIdEntity.kt new file mode 100644 index 0000000..19c1c44 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableLongIdEntity.kt @@ -0,0 +1,17 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.models + +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id +import javax.persistence.MappedSuperclass + +@Suppress("unused") +@MappedSuperclass +abstract class AuditableLongIdEntity : AuditableEntity() { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + open var id: Long? = null + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableUuidIdEntity.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableUuidIdEntity.kt new file mode 100644 index 0000000..ef6f825 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/AuditableUuidIdEntity.kt @@ -0,0 +1,19 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.models + +import org.hibernate.annotations.GenericGenerator +import java.util.UUID +import javax.persistence.GeneratedValue +import javax.persistence.Id +import javax.persistence.MappedSuperclass + +@Suppress("unused") +@MappedSuperclass +abstract class AuditableUuidIdEntity : AuditableEntity() { + + @Id + @GeneratedValue(generator = "uuid") + @GenericGenerator(name = "uuid", strategy = "uuid2") + open var id: UUID? = null + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseEntity.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseEntity.kt new file mode 100644 index 0000000..f218f67 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseEntity.kt @@ -0,0 +1,22 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.models + +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.io.Serializable +import java.time.ZonedDateTime +import javax.persistence.EntityListeners +import javax.persistence.MappedSuperclass + +@EntityListeners(AuditingEntityListener::class) +@MappedSuperclass +abstract class BaseEntity : Serializable { + + @CreatedDate + lateinit var createdAt: ZonedDateTime + + @LastModifiedDate + var updatedAt: ZonedDateTime? = null + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseLongIdEntity.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseLongIdEntity.kt new file mode 100644 index 0000000..09ff233 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseLongIdEntity.kt @@ -0,0 +1,17 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.models + +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id +import javax.persistence.MappedSuperclass + +@Suppress("unused") +@MappedSuperclass +abstract class BaseLongIdEntity : BaseEntity() { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + open var id: Long? = null + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseUuidIdEntity.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseUuidIdEntity.kt new file mode 100644 index 0000000..673c726 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/models/BaseUuidIdEntity.kt @@ -0,0 +1,19 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.models + +import org.hibernate.annotations.GenericGenerator +import java.util.UUID +import javax.persistence.GeneratedValue +import javax.persistence.Id +import javax.persistence.MappedSuperclass + +@Suppress("unused") +@MappedSuperclass +abstract class BaseUuidIdEntity : BaseEntity() { + + @Id + @GeneratedValue(generator = "uuid") + @GenericGenerator(name = "uuid", strategy = "uuid2") + open var id: UUID? = null + +} diff --git a/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/repositories/RepositoryUtils.kt b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/repositories/RepositoryUtils.kt new file mode 100644 index 0000000..21b6a09 --- /dev/null +++ b/common-spring-jpa/src/main/kotlin/ru/touchin/common/spring/jpa/repositories/RepositoryUtils.kt @@ -0,0 +1,14 @@ +@file:Suppress("unused") +package ru.touchin.common.spring.jpa.repositories + +object RepositoryUtils { + + const val SKIP_LOCKED_PARAMETER = "javax.persistence.lock.timeout" + + /** + * Const value which is used for 'SKIP LOCKED' in 'SELECT ... FOR UPDATE' query + */ + const val SKIP_LOCKED_VALUE = "-2" + +} + diff --git a/settings.gradle.kts b/settings.gradle.kts index 4ad10bb..01aa268 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,3 +22,4 @@ pluginManagement { include("common") include("common-spring") +include("common-spring-jpa")