micronaut-projects / micronaut-data

Ahead of Time Data Repositories
Apache License 2.0
465 stars 196 forks source link

findBy..ForUpdate not Working #3117

Closed joaquindiez closed 1 week ago

joaquindiez commented 2 weeks ago

Expected Behavior

Una Repository Interfaze is expected ( as the documentation explains) that when defining a fun findAllByTypeAndStatusForUpdate method a SELECT FOR UPDATE query is generated

Actual Behaviour

A repository like

`import io.micronaut.data.annotation.Query import io.micronaut.data.annotation.Repository import io.micronaut.data.model.Pageable import io.micronaut.data.repository.CrudRepository

import switchfleet.api.tasks.domain.TaskStatus import switchfleet.api.tasks.domain.TaskType import switchfleet.api.tasks.domain.Tasks import java.util.UUID

@Repository interface TaskRepository : CrudRepository<Tasks, UUID> {

@Query("FROM Tasks tasks WHERE tasks.type = :type AND tasks.status = :status") fun findAllByTypeAndStatusForUpdate(type: TaskType, status: TaskStatus, pageable: Pageable): List }

Doen no generate the SELECT FOR UPDATE

`

Steps To Reproduce

I am using Micronaut 4.6.1

Code

Repository

`import io.micronaut.data.annotation.Query import io.micronaut.data.annotation.Repository import io.micronaut.data.model.Pageable import io.micronaut.data.repository.CrudRepository

import switchfleet.api.tasks.domain.TaskStatus import switchfleet.api.tasks.domain.TaskType import switchfleet.api.tasks.domain.Tasks import java.util.UUID

@Repository interface TaskRepository : CrudRepository<Tasks, UUID> {

@Query("FROM Tasks tasks WHERE tasks.type = :type AND tasks.status = :status") fun findAllByTypeAndStatusForUpdate(type: TaskType, status: TaskStatus, pageable: Pageable): List } `

Entity

` package switchfleet.api.tasks.domain

import io.micronaut.data.annotation.DateCreated import io.micronaut.serde.annotation.Serdeable import jakarta.persistence. import java.time.LocalDateTime import java.util.

enum class TaskStatus { PENDING, DONE, IN_PROGRESS }

enum class TaskType { SEND_EMAIL, }

@Serdeable @Entity @Table(name = "tasks") data class Tasks(

@Id @Column(name = "id", nullable = false) val id: UUID,

@Enumerated(value = EnumType.STRING) val type:TaskType,

@Column(name = "metadata", nullable = false, unique = false) val metadata: String,

@Enumerated(value = EnumType.STRING) var status: TaskStatus = TaskStatus.PENDING,

@field:DateCreated @Column(name = "created_at", nullable = false) val createdAt: LocalDateTime = LocalDateTime.now(),

@field:DateCreated @Column(name = "updated_at", nullable = false) val updatedAt: LocalDateTime = LocalDateTime.now()

) `

Environment Information

Example Application

No response

Version

4.6.1

radovanradic commented 2 weeks ago

I think you can use Micronaut Data @QueryHint annotation to have for update query in Hibernate. You can replace this method

@Query("FROM Tasks tasks WHERE tasks.type = :type AND tasks.status = :status")
fun findAllByTypeAndStatusForUpdate(type: TaskType, status: TaskStatus, pageable: Pageable): List

with this (don't have to use @Query although you can)

@QueryHint(name = "org.hibernate.lockMode", value = "pessimistic_write")
fun findAllByTypeAndStatus(type: TaskType, status: TaskStatus, pageable: Pageable): List
radovanradic commented 1 week ago

findForUpdate is supported only for jdbc/r2dbc and for jpa the suggestion in the comment above can be used. I think we can close this, please reopen if you think it needs some changes.