diff --git a/351003/brezgunov/distcomp/build.gradle.kts b/351003/brezgunov/distcomp/build.gradle.kts index ecefd45dd..1e9ce0ee5 100644 --- a/351003/brezgunov/distcomp/build.gradle.kts +++ b/351003/brezgunov/distcomp/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("jvm") version "2.3.0" kotlin("plugin.spring") version "2.3.0" + kotlin("plugin.jpa") version "2.3.0" kotlin("kapt") version "2.3.0" id("org.springframework.boot") version "4.0.2" id("io.spring.dependency-management") version "1.1.7" @@ -22,11 +23,14 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-webmvc") + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("tools.jackson.module:jackson-module-kotlin") implementation("org.mapstruct:mapstruct:1.7.0.Beta1") implementation("org.springframework.boot:spring-boot-starter-actuator") kapt("org.mapstruct:mapstruct-processor:1.7.0.Beta1") + runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-webmvc-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/MarkerController.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/MarkerController.kt index bd2c03ce0..14adf5076 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/MarkerController.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/MarkerController.kt @@ -3,6 +3,7 @@ package com.distcomp.controller import com.distcomp.dto.marker.MarkerRequestTo import com.distcomp.dto.marker.MarkerResponseTo import com.distcomp.service.MarkerService +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* @@ -13,7 +14,7 @@ class MarkerController( ) { @PostMapping(version = "1.0") @ResponseStatus(HttpStatus.CREATED) - fun createMarker(@RequestBody markerRequestTo: MarkerRequestTo): MarkerResponseTo { + fun createMarker(@Valid @RequestBody markerRequestTo: MarkerRequestTo): MarkerResponseTo { return markerService.createMarker(markerRequestTo) } @@ -30,7 +31,7 @@ class MarkerController( @PutMapping(path = ["/{id}", ""], version = "1.0") @ResponseStatus(HttpStatus.OK) fun updateMarker( - @RequestBody markerRequestTo: MarkerRequestTo, + @Valid @RequestBody markerRequestTo: MarkerRequestTo, @PathVariable("id") id: Long? ): MarkerResponseTo { return markerService.updateMarker(markerRequestTo, id) diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NewsController.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NewsController.kt index 3ce81f995..acd918acd 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NewsController.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NewsController.kt @@ -3,6 +3,7 @@ package com.distcomp.controller import com.distcomp.dto.news.NewsRequestTo import com.distcomp.dto.news.NewsResponseTo import com.distcomp.service.NewsService +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping @@ -21,7 +22,7 @@ class NewsController ( ) { @PostMapping(version = "1.0") @ResponseStatus(HttpStatus.CREATED) - fun createUser(@RequestBody newsRequestTo: NewsRequestTo): NewsResponseTo { + fun createUser(@Valid @RequestBody newsRequestTo: NewsRequestTo): NewsResponseTo { return newsService.createNews(newsRequestTo) } @@ -37,7 +38,7 @@ class NewsController ( @PutMapping(path = ["/{id}", ""], version = "1.0") @ResponseStatus(HttpStatus.OK) - fun updateUser(@RequestBody newsRequestTo: NewsRequestTo, + fun updateUser(@Valid @RequestBody newsRequestTo: NewsRequestTo, @PathVariable("id") userId: Long?): NewsResponseTo { return newsService.updateNews(newsRequestTo, userId) } diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NoticeController.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NoticeController.kt index 333d8fc47..a615a820d 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NoticeController.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/NoticeController.kt @@ -3,6 +3,7 @@ package com.distcomp.controller import com.distcomp.dto.notice.NoticeRequestTo import com.distcomp.dto.notice.NoticeResponseTo import com.distcomp.service.NoticeService +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.* @@ -13,7 +14,7 @@ class NoticeController( ) { @PostMapping(version = "1.0") @ResponseStatus(HttpStatus.CREATED) - fun createNotice(@RequestBody noticeRequestTo: NoticeRequestTo): NoticeResponseTo { + fun createNotice(@Valid @RequestBody noticeRequestTo: NoticeRequestTo): NoticeResponseTo { return noticeService.createNotice(noticeRequestTo) } @@ -30,7 +31,7 @@ class NoticeController( @PutMapping(path = ["/{id}", ""], version = "1.0") @ResponseStatus(HttpStatus.OK) fun updateNotice( - @RequestBody noticeRequestTo: NoticeRequestTo, + @Valid @RequestBody noticeRequestTo: NoticeRequestTo, @PathVariable("id") id: Long? ): NoticeResponseTo { return noticeService.updateNotice(noticeRequestTo, id) diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/UserController.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/UserController.kt index 7c7e6fdf0..cdff60dd4 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/UserController.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/controller/UserController.kt @@ -3,6 +3,7 @@ package com.distcomp.controller import com.distcomp.dto.user.UserRequestTo import com.distcomp.dto.user.UserResponseTo import com.distcomp.service.UserService +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping @@ -21,7 +22,7 @@ class UserController ( ) { @PostMapping(version = "1.0") @ResponseStatus(HttpStatus.CREATED) - fun createUser(@RequestBody userRequestTo: UserRequestTo): UserResponseTo { + fun createUser(@Valid @RequestBody userRequestTo: UserRequestTo): UserResponseTo { return userService.createUser(userRequestTo) } @@ -37,7 +38,7 @@ class UserController ( @PutMapping(version = "1.0") @ResponseStatus(HttpStatus.OK) - fun updateUser(@RequestBody userRequestTo: UserRequestTo): UserResponseTo { + fun updateUser(@Valid @RequestBody userRequestTo: UserRequestTo): UserResponseTo { return userService.updateUser(userRequestTo) } diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/marker/MarkerRequestTo.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/marker/MarkerRequestTo.kt index e6901d1ca..9c48764e3 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/marker/MarkerRequestTo.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/marker/MarkerRequestTo.kt @@ -1,6 +1,11 @@ package com.distcomp.dto.marker +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Size + data class MarkerRequestTo( val id: Long? = null, + @field:NotBlank + @field:Size(min = 3, max = 32) val name: String, ) diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/news/NewsRequestTo.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/news/NewsRequestTo.kt index dc48e090b..895de7009 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/news/NewsRequestTo.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/news/NewsRequestTo.kt @@ -1,8 +1,19 @@ package com.distcomp.dto.news +import com.distcomp.dto.marker.MarkerRequestTo +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size + data class NewsRequestTo ( val id: Long? = null, + @field:NotBlank + @field:Size(min = 3, max = 64) val title: String, + @field:NotBlank + @field:Size(min = 4, max = 2048) val content: String, - val userId: Long + @field:NotNull + val userId: Long, + val markers: List?, ) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/notice/NoticeRequestTo.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/notice/NoticeRequestTo.kt index 107b73b35..fa01454e8 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/notice/NoticeRequestTo.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/notice/NoticeRequestTo.kt @@ -1,7 +1,14 @@ package com.distcomp.dto.notice +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size + data class NoticeRequestTo ( val id: Long? = null, + @field:NotNull val newsId: Long, + @field:NotBlank + @field:Size(min = 4, max = 2048) val content: String ) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/user/UserRequestTo.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/user/UserRequestTo.kt index 6a7329984..6163471c3 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/user/UserRequestTo.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/dto/user/UserRequestTo.kt @@ -1,9 +1,20 @@ package com.distcomp.dto.user +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Size + data class UserRequestTo( val id: Long? = null, + @field:NotBlank + @field:Size(min = 2, max = 64) val login: String, + @field:NotBlank + @field:Size(min = 8, max = 128) val password: String, + @field:NotBlank + @field:Size(min = 2, max = 64) val firstname: String, + @field:NotBlank + @field:Size(min = 2, max = 64) val lastname: String, ) diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Marker.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Marker.kt index 368a76c77..83b63a658 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Marker.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Marker.kt @@ -1,6 +1,12 @@ package com.distcomp.entity -class Marker ( - var id: Long, +import jakarta.persistence.* + +@Entity +@Table(name = "tbl_marker") +class Marker( + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + var id: Long = 0, var name: String, ) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/News.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/News.kt index 055e73049..de31acaaf 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/News.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/News.kt @@ -1,12 +1,23 @@ package com.distcomp.entity +import jakarta.persistence.* +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Size import java.time.LocalDateTime +@Entity +@Table(name = "tbl_news") class News( + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) var id: Long? = null, var title: String, var content: String, var created: LocalDateTime = LocalDateTime.now(), var modified: LocalDateTime = LocalDateTime.now(), - var user: User? = null + @ManyToOne + @JoinColumn(name = "user_id") + var user: User? = null, + @OneToMany(cascade = [(CascadeType.ALL)], orphanRemoval = true) + var markers: MutableList = mutableListOf(), ) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Notice.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Notice.kt index a4c831855..ac4d57527 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Notice.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/Notice.kt @@ -1,7 +1,15 @@ package com.distcomp.entity -class Notice ( +import jakarta.persistence.* + +@Entity +@Table(name = "tbl_notice") +class Notice( + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) var id: Long, var content: String, + @ManyToOne + @JoinColumn(name = "news_id") var news: News? = null ) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/User.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/User.kt index 86fff086f..3e2873996 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/User.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/entity/User.kt @@ -1,10 +1,17 @@ package com.distcomp.entity -class User ( +import jakarta.persistence.* + +@Entity +@Table(name = "tbl_user") +class User( + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) var id: Long? = null, var login: String, var password: String, var firstname: String, var lastname: String, - var news: List? + @OneToMany(mappedBy = "user", cascade = [CascadeType.ALL]) + var news: MutableList? = null ) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/exception/DuplicateUserException.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/exception/DuplicateUserException.kt new file mode 100644 index 000000000..58ed08564 --- /dev/null +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/exception/DuplicateUserException.kt @@ -0,0 +1,6 @@ +package com.distcomp.exception + +import org.springframework.http.HttpStatus + +class DuplicateUserException(errorMsg: String) : + AbstractException(HttpStatus.FORBIDDEN, errorMsg) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/exception/NewsTitleDuplicateException.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/exception/NewsTitleDuplicateException.kt new file mode 100644 index 000000000..6575aa0c0 --- /dev/null +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/exception/NewsTitleDuplicateException.kt @@ -0,0 +1,6 @@ +package com.distcomp.exception + +import org.springframework.http.HttpStatus + +class NewsTitleDuplicateException (errorMessage: String) + : AbstractException(HttpStatus.FORBIDDEN, errorMessage) \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/CrudRepository.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/CrudRepository.kt deleted file mode 100644 index e5627c2ce..000000000 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/CrudRepository.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.distcomp.repository - -interface CrudRepository { - fun save(entity: T) - - fun findById(id: Long): T? - - fun findAll(): List - - fun removeById(id: Long) -} \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/MarkerRepository.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/MarkerRepository.kt new file mode 100644 index 000000000..412866252 --- /dev/null +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/MarkerRepository.kt @@ -0,0 +1,6 @@ +package com.distcomp.repository + +import com.distcomp.entity.Marker +import org.springframework.data.jpa.repository.JpaRepository + +interface MarkerRepository : JpaRepository diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/MarkerRepositoryInMem.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/MarkerRepositoryInMem.kt deleted file mode 100644 index d112e78a4..000000000 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/MarkerRepositoryInMem.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.distcomp.repository - -import com.distcomp.entity.Marker -import org.springframework.stereotype.Repository -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicLong - -@Repository -class MarkerRepositoryInMem : CrudRepository { - private val markerMap = ConcurrentHashMap() - private val counter = AtomicLong(0L) - - override fun save(entity: Marker) { - val index = if (entity.id == null) { - val newId = counter.incrementAndGet() - entity.id = newId - newId - } else { - entity.id!! - } - - markerMap[index] = entity - } - - override fun findById(id: Long): Marker? { - return markerMap[id] - } - - override fun findAll(): List { - return markerMap.values.toList() - } - - override fun removeById(id: Long) { - markerMap.remove(id) - } -} \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NewsRepository.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NewsRepository.kt new file mode 100644 index 000000000..f6655b107 --- /dev/null +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NewsRepository.kt @@ -0,0 +1,8 @@ +package com.distcomp.repository + +import com.distcomp.entity.News +import org.springframework.data.jpa.repository.JpaRepository + +interface NewsRepository : JpaRepository { + fun existsByTitle(title: String): Boolean +} diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NewsRepositoryInMem.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NewsRepositoryInMem.kt deleted file mode 100644 index 2b9b2d67d..000000000 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NewsRepositoryInMem.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.distcomp.repository - -import com.distcomp.entity.News -import org.springframework.stereotype.Repository -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicLong -import kotlin.collections.set - -@Repository -class NewsRepositoryInMem : CrudRepository { - private val newsMap = ConcurrentHashMap() - private val counter = AtomicLong(0L) - - override fun save(news: News) { - val index = if (news.id == null) { - val newId = counter.incrementAndGet() - news.id = newId - newId - } else { - news.id!! - } - - newsMap[index] = news - } - - override fun findById(id: Long): News? { - return newsMap[id] - } - - override fun findAll(): List { - return newsMap.values.toList() - } - - override fun removeById(id: Long) { - newsMap.remove(id) - } -} \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NoticeRepository.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NoticeRepository.kt new file mode 100644 index 000000000..4e4dcb529 --- /dev/null +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NoticeRepository.kt @@ -0,0 +1,6 @@ +package com.distcomp.repository + +import com.distcomp.entity.Notice +import org.springframework.data.jpa.repository.JpaRepository + +interface NoticeRepository : JpaRepository diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NoticeRepositoryInMem.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NoticeRepositoryInMem.kt deleted file mode 100644 index 4afe7a029..000000000 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/NoticeRepositoryInMem.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.distcomp.repository - -import com.distcomp.entity.Notice -import org.springframework.stereotype.Repository -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicLong - -@Repository -class NoticeRepositoryInMem : CrudRepository { - private val noticeMap = ConcurrentHashMap() - private val counter = AtomicLong(0L) - - override fun save(notice: Notice) { - val index = if (notice.id == null) { - val newId = counter.incrementAndGet() - notice.id = newId - newId - } else { - notice.id!! - } - - noticeMap[index] = notice - } - - override fun findById(id: Long): Notice? { - return noticeMap[id] - } - - override fun findAll(): List { - return noticeMap.values.toList() - } - - override fun removeById(id: Long) { - noticeMap.remove(id) - } -} \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/UserRepository.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/UserRepository.kt new file mode 100644 index 000000000..dcc344a3a --- /dev/null +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/UserRepository.kt @@ -0,0 +1,8 @@ +package com.distcomp.repository + +import com.distcomp.entity.User +import org.springframework.data.jpa.repository.JpaRepository + +interface UserRepository : JpaRepository { + fun existsByLogin(login: String): Boolean +} diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/UserRepositoryInMem.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/UserRepositoryInMem.kt deleted file mode 100644 index aa003afae..000000000 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/repository/UserRepositoryInMem.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.distcomp.repository - -import com.distcomp.entity.User -import org.springframework.stereotype.Repository -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicLong - -@Repository -class UserRepositoryInMem : CrudRepository { - private val userMap = ConcurrentHashMap() - private val counter = AtomicLong(0L) - - override fun save(user: User) { - val index = if (user.id == null) { - val newId = counter.incrementAndGet() - user.id = newId - newId - } else { - user.id!! - } - - userMap[index] = user - } - - override fun findById(id: Long): User? { - return userMap[id] - } - - override fun findAll(): List { - return userMap.values.toList() - } - - override fun removeById(id: Long) { - userMap.remove(id) - } -} diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/MarkerService.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/MarkerService.kt index b04507d23..2c4e422b2 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/MarkerService.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/MarkerService.kt @@ -2,17 +2,19 @@ package com.distcomp.service import com.distcomp.dto.marker.MarkerRequestTo import com.distcomp.dto.marker.MarkerResponseTo -import com.distcomp.entity.Marker import com.distcomp.exception.MarkerNotFoundException import com.distcomp.mapper.MarkerMapper -import com.distcomp.repository.CrudRepository +import com.distcomp.repository.MarkerRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service class MarkerService( val markerMapper: MarkerMapper, - val markerRepository: CrudRepository + val markerRepository: MarkerRepository ) { + @Transactional fun createMarker(markerRequestTo: MarkerRequestTo): MarkerResponseTo { val marker = markerMapper.toMarkerEntity(markerRequestTo) markerRepository.save(marker) @@ -20,7 +22,7 @@ class MarkerService( } fun readMarkerById(id: Long): MarkerResponseTo { - val marker = markerRepository.findById(id) + val marker = markerRepository.findByIdOrNull(id) ?: throw MarkerNotFoundException("Marker with id $id not found") return markerMapper.toMarkerResponse(marker) } @@ -29,8 +31,9 @@ class MarkerService( return markerRepository.findAll().map { markerMapper.toMarkerResponse(it) } } + @Transactional fun updateMarker(markerRequestTo: MarkerRequestTo, markerId: Long?): MarkerResponseTo { - if (markerId == null || markerRepository.findById(markerId) == null) { + if (markerId == null || markerRepository.findByIdOrNull(markerId) == null) { throw MarkerNotFoundException("Marker with id $markerId not found") } @@ -41,10 +44,11 @@ class MarkerService( return markerMapper.toMarkerResponse(marker) } + @Transactional fun removeMarkerById(id: Long) { - if (markerRepository.findById(id) == null) { + if (markerRepository.findByIdOrNull(id) == null) { throw MarkerNotFoundException("Marker with id $id not found") } - markerRepository.removeById(id) + markerRepository.deleteById(id) } } \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NewsService.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NewsService.kt index e859a06e2..9229ef2ab 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NewsService.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NewsService.kt @@ -2,39 +2,59 @@ package com.distcomp.service import com.distcomp.dto.news.NewsRequestTo import com.distcomp.dto.news.NewsResponseTo -import com.distcomp.entity.News -import com.distcomp.entity.User +import com.distcomp.entity.Marker import com.distcomp.exception.NewsNotFoundException +import com.distcomp.exception.NewsTitleDuplicateException +import com.distcomp.exception.UserNotFoundException import com.distcomp.exception.ValidationException import com.distcomp.mapper.NewsMapper -import com.distcomp.repository.CrudRepository +import com.distcomp.repository.MarkerRepository +import com.distcomp.repository.NewsRepository +import com.distcomp.repository.UserRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service -class NewsService ( +class NewsService( val newsMapper: NewsMapper, - val newsRepository: CrudRepository, - val userRepository: CrudRepository + val newsRepository: NewsRepository, + val userRepository: UserRepository, + val markerRepository: MarkerRepository ) { + @Transactional fun createNews(newsRequestTo: NewsRequestTo): NewsResponseTo { + if (newsRepository.existsByTitle(newsRequestTo.title)) { + throw NewsTitleDuplicateException("Title already exists") + } + val news = newsMapper.toNewsEntity(newsRequestTo) - newsRepository.save(news) - val user = userRepository.findById(newsRequestTo.userId) + val user = userRepository.findByIdOrNull(newsRequestTo.userId) + ?: throw UserNotFoundException("User not found") news.user = user + + if (newsRequestTo.markers != null) { + for (markerName in newsRequestTo.markers) { + news.markers.add(Marker(name = markerName)) + } + } + + newsRepository.save(news) return newsMapper.toNewsResponse(news) } fun readNewsById(id: Long): NewsResponseTo { - val user = newsRepository.findById(id) ?: throw NewsNotFoundException("User not found") - return newsMapper.toNewsResponse(user) + val news = newsRepository.findByIdOrNull(id) ?: throw NewsNotFoundException("User not found") + return newsMapper.toNewsResponse(news) } fun readAll(): List { return newsRepository.findAll().map { newsMapper.toNewsResponse(it) } } + @Transactional fun updateNews(newsRequestTo: NewsRequestTo, newsId: Long?): NewsResponseTo { - if (newsId == null || newsRepository.findById(newsId) == null) { + if (newsId == null || newsRepository.findByIdOrNull(newsId) == null) { throw NewsNotFoundException("User not found") } @@ -44,17 +64,18 @@ class NewsService ( val news = newsMapper.toNewsEntity(newsRequestTo) news.id = newsId - newsRepository.save(news) - val user = userRepository.findById(newsRequestTo.userId) + val user = userRepository.findByIdOrNull(newsRequestTo.userId) news.user = user + newsRepository.save(news) return newsMapper.toNewsResponse(news) } + @Transactional fun removeNewsById(id: Long) { - if (newsRepository.findById(id) == null) { + if (newsRepository.findByIdOrNull(id) == null) { throw NewsNotFoundException("News not found") } - newsRepository.removeById(id) + newsRepository.deleteById(id) } } \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NoticeService.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NoticeService.kt index a9f322ed5..55425d5d4 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NoticeService.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/NoticeService.kt @@ -2,30 +2,32 @@ package com.distcomp.service import com.distcomp.dto.notice.NoticeRequestTo import com.distcomp.dto.notice.NoticeResponseTo -import com.distcomp.entity.News -import com.distcomp.entity.Notice import com.distcomp.exception.NewsNotFoundException import com.distcomp.exception.NoticeNotFoundException import com.distcomp.mapper.NoticeMapper -import com.distcomp.repository.CrudRepository +import com.distcomp.repository.NewsRepository +import com.distcomp.repository.NoticeRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service class NoticeService( val noticeMapper: NoticeMapper, - val noticeRepository: CrudRepository, - val newsRepository: CrudRepository + val noticeRepository: NoticeRepository, + val newsRepository: NewsRepository ) { + @Transactional fun createNotice(noticeRequestTo: NoticeRequestTo): NoticeResponseTo { val notice = noticeMapper.toNoticeEntity(noticeRequestTo) - noticeRepository.save(notice) - val news = newsRepository.findById(noticeRequestTo.newsId) + val news = newsRepository.findByIdOrNull(noticeRequestTo.newsId) notice.news = news ?: throw NewsNotFoundException("News not found") + noticeRepository.save(notice) return noticeMapper.toNoticeResponse(notice) } fun readNoticeById(id: Long): NoticeResponseTo { - val notice = noticeRepository.findById(id) + val notice = noticeRepository.findByIdOrNull(id) ?: throw NoticeNotFoundException("Notice with id $id not found") return noticeMapper.toNoticeResponse(notice) } @@ -34,26 +36,28 @@ class NoticeService( return noticeRepository.findAll().map { noticeMapper.toNoticeResponse(it) } } + @Transactional fun updateNotice(noticeRequestTo: NoticeRequestTo, noticeId: Long?): NoticeResponseTo { - if (noticeId == null || noticeRepository.findById(noticeId) == null) { + if (noticeId == null || noticeRepository.findByIdOrNull(noticeId) == null) { throw NoticeNotFoundException("Notice with id $noticeId not found") } val notice = noticeMapper.toNoticeEntity(noticeRequestTo) notice.id = noticeId - noticeRepository.save(notice) - val news = newsRepository.findById(noticeRequestTo.newsId) + val news = newsRepository.findByIdOrNull(noticeRequestTo.newsId) notice.news = news ?: throw NewsNotFoundException("News not found") + noticeRepository.save(notice) return noticeMapper.toNoticeResponse(notice) } + @Transactional fun removeNoticeById(id: Long) { - if (noticeRepository.findById(id) == null) { + if (noticeRepository.findByIdOrNull(id) == null) { throw NoticeNotFoundException("Notice with id $id not found") } - noticeRepository.removeById(id) + noticeRepository.deleteById(id) } } \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/UserService.kt b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/UserService.kt index cac4dcc48..0544adb9b 100644 --- a/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/UserService.kt +++ b/351003/brezgunov/distcomp/src/main/kotlin/com/distcomp/service/UserService.kt @@ -2,26 +2,32 @@ package com.distcomp.service import com.distcomp.dto.user.UserRequestTo import com.distcomp.dto.user.UserResponseTo -import com.distcomp.entity.User +import com.distcomp.exception.DuplicateUserException import com.distcomp.exception.UserNotFoundException import com.distcomp.mapper.UserMapper -import com.distcomp.repository.CrudRepository -import org.springframework.beans.factory.annotation.Qualifier +import com.distcomp.repository.UserRepository +import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service -class UserService ( +class UserService( val userMapper: UserMapper, - @Qualifier("userRepositoryInMem") val userRepository: CrudRepository + val userRepository: UserRepository ) { + @Transactional fun createUser(userRequestTo: UserRequestTo): UserResponseTo { + if (userRepository.existsByLogin(userRequestTo.login)) { + throw DuplicateUserException("User with login already exists") + } + val user = userMapper.toUserEntity(userRequestTo) userRepository.save(user) return userMapper.toUserResponse(user) } fun readUserById(id: Long): UserResponseTo { - val user = userRepository.findById(id) ?: throw UserNotFoundException("User not found") + val user = userRepository.findByIdOrNull(id) ?: throw UserNotFoundException("User not found") return userMapper.toUserResponse(user) } @@ -29,8 +35,9 @@ class UserService ( return userRepository.findAll().map { userMapper.toUserResponse(it) } } + @Transactional fun updateUser(userRequestTo: UserRequestTo): UserResponseTo { - if (userRequestTo.id == null || userRepository.findById(userRequestTo.id) == null) { + if (userRequestTo.id == null || userRepository.findByIdOrNull(userRequestTo.id) == null) { throw UserNotFoundException("User not found") } @@ -39,11 +46,12 @@ class UserService ( return userMapper.toUserResponse(user) } + @Transactional fun removeUserById(id: Long) { - if (userRepository.findById(id) == null) { + if (userRepository.findByIdOrNull(id) == null) { throw UserNotFoundException("User not found") } - userRepository.removeById(id) + userRepository.deleteById(id) } } \ No newline at end of file diff --git a/351003/brezgunov/distcomp/src/main/resources/application.yaml b/351003/brezgunov/distcomp/src/main/resources/application.yaml index f06fdc777..4297e9698 100644 --- a/351003/brezgunov/distcomp/src/main/resources/application.yaml +++ b/351003/brezgunov/distcomp/src/main/resources/application.yaml @@ -7,6 +7,18 @@ spring: path-segment: 1 supported: 1.0, 2.0 default: 1.0 + datasource: + url: jdbc:postgresql://localhost:5432/distcomp + username: postgres + password: postgres + driver-class-name: org.postgresql.Driver + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect server: port: 24110