gpt4 book ai didi

java - Spring Data JPA - 是否可以在将实体保留在存储库中之前使用主体更新实体?

转载 作者:行者123 更新时间:2023-12-02 06:05:36 24 4
gpt4 key购买 nike

我想使用 Spring Security 5 保护我的资源服务器,以便可供许多用户使用。我有一个实体Task其中包含一个字段 userId .

@Entity
@Table(name = "tasks")
data class Task(
@NotBlank
val name: String,

val description: String?,

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "task_id_seq")
val id: Long = 0,

@UUID //custom validation annotation
val userId: String? = null
)

我找到了一种使用 SpEL 在查询中注入(inject) JWT 主体的方法。我已经做的是我已经覆盖 findAll()我的方法interface TaskRepository : JpaRepository<Task, Long>@Query注释:

@Query("select t from Task t where t.userId = :#{principal.claims['sub']}")
//sub is a userId in OpenID Connect 1.0, claim is a Map<String, Object>
override fun findAll(): List<Task>

问题是我想做类似 save() 的事情方法。我发现的唯一一件事就是对已保存的实体进行更新。我创建了一个全新的方法:

@Modifying
@Query("update Task t set t.userId = :#{principal.claims['sub']} where t.id = :id")
fun setUserId(@Param("id") id: Long)

但问题是我需要在我的 TaskService 中调用这个方法,如下所示:

@Transactional
fun createTask(taskDto: CreateTaskDto): Task {
val task = taskRepository.save(taskDto.toEntity())
taskRepository.setUserId(task.id)
return task
}

每次在数据库中保存实体时是否可以自动添加此信息?那么我在 TaskService 中的代码将如下所示:

@Transactional
fun createTask(taskDto: CreateTaskDto): Task {
return taskRepository.save(taskDto.toEntity())
}

最佳答案

解决方案实际上很简单,但我不知道我在寻找什么。不过,我不知道这是否是一个规范的解决方案。我为此使用 Jpa 审计。首先,我添加了@CreatedBy在插入实体之前我想要更新的字段的注释。实体类我也用@EntityListeners(AuditingEntityListener::class)注释。请注意,需要更改 val关键字为var (从 final 字段到 Java 世界中的非最终字段)。

@Entity
@Table(name = "tasks")
@EntityListeners(AuditingEntityListener::class)
data class Task(
@NotBlank
val name: String,

val description: String?,

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "task_id_seq")
val id: Long = 0,

@UUID
@CreatedBy
var userId: String? = null
)

下一步是实现interface AuditorAware<T>并通过使用@Component(或在配置类中创建一个bean)使其对Spring可见

@Component
class SpringSecurityAuditorAware : AuditorAware<String> {

override fun getCurrentAuditor(): Optional<String> {
return Optional.ofNullable(SecurityContextHolder.getContext()?.authentication)
.filter { authentication -> authentication.isAuthenticated }
.map { authentication -> authentication.principal as Jwt }
.map { jwt -> jwt.claims["sub"] as String? }
}

}

最后但并非最不重要的一点是在某些配置类上添加 @EnableJpaAuditing:

@Configuration
@EnableJpaAuditing
class ResourceServerContext

关于java - Spring Data JPA - 是否可以在将实体保留在存储库中之前使用主体更新实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55941695/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com