Spring data/Hibernate: 分离的实体传递给持久化
Spring data/Hibernate: detached entity passed to persist
我得到“已分离的实体传递给持久化”,但我不明白,所讨论的对象如何处于分离状态。
首先是一些上下文。
每个用户和角色两个 JpaRepository
:
@Repository
interface RoleRepository : JpaRepository<UserRole, Long> {
fun findByName(name: String): UserRole?
}
@Repository
interface BackendUserRepository : JpaRepository<BackendUser, Long> {
fun findByUserName(name: String): BackendUser?
}
BackendUser
实体 - 除了名称 - 有几个字段不应与此问题相关,外部字段角色来自其基础 class:
abstract class User(
@ManyToOne(fetch = FetchType.LAZY, cascade = arrayOf(CascadeType.ALL), optional = false)
@JoinColumn(referencedColumnName = "name", nullable = false)
var role: UserRole
) : UserDetails {
// ...
}
在应用程序启动时,我想确保此 ApplicationRunner 中存在管理员用户:
@Component
class InitialDataApplicationRunner : ApplicationRunner {
@Autowired
lateinit var roles: RoleRepository
@Autowired
lateinit var users: BackendUserRepository
override fun run(args: ApplicationArguments) {
// some other stuff
createAdminUser()
}
@Transactional
private fun createAdminUser() {
if (users.findByUserName("admin") == null) {
val adminRole = roles.findByName("admin")!!
val adminUser = BackendUser("admin", adminRole
// some more data here
)
users.save(adminUser)
}
}
}
应用程序在启动和关闭时抛出异常:
org.hibernate.PersistentObjectException: detached entity passed to
persist: my.package.name.user.UserRole
我在这里的理解是,adminRole
在从存储库中检索后立即处于分离状态。
- 为什么会分离?我曾假设方法上的 @Transactional 注释将确保一切都发生在相同的持久性上下文中,而这不应该发生。
- 我该如何防止这种情况发生?有没有办法不用删除级联选项
- 关于 spring/jpa 和 hibernate 如何协同工作是否有任何好的信息来源 - 到目前为止,我发现的任何东西都没有真正帮助我详细理解这些概念,以及 respositoryies 如何隐藏实体您在尝试阅读休眠时发现的管理和会话概念。
由于您在私有方法上使用了@Transactional,并且还从同一个方法中调用了一个方法class,因此没有事务,因此分离状态用于保存(see this)。
不确定您是否可以在 运行() 或此 class 上应用 @Transactional。
无论如何,也许您应该使用 public @Transactional 方法创建新的“服务”class,然后从您的 class.
调用此服务
我得到“已分离的实体传递给持久化”,但我不明白,所讨论的对象如何处于分离状态。
首先是一些上下文。
每个用户和角色两个 JpaRepository
:
@Repository
interface RoleRepository : JpaRepository<UserRole, Long> {
fun findByName(name: String): UserRole?
}
@Repository
interface BackendUserRepository : JpaRepository<BackendUser, Long> {
fun findByUserName(name: String): BackendUser?
}
BackendUser
实体 - 除了名称 - 有几个字段不应与此问题相关,外部字段角色来自其基础 class:
abstract class User(
@ManyToOne(fetch = FetchType.LAZY, cascade = arrayOf(CascadeType.ALL), optional = false)
@JoinColumn(referencedColumnName = "name", nullable = false)
var role: UserRole
) : UserDetails {
// ...
}
在应用程序启动时,我想确保此 ApplicationRunner 中存在管理员用户:
@Component
class InitialDataApplicationRunner : ApplicationRunner {
@Autowired
lateinit var roles: RoleRepository
@Autowired
lateinit var users: BackendUserRepository
override fun run(args: ApplicationArguments) {
// some other stuff
createAdminUser()
}
@Transactional
private fun createAdminUser() {
if (users.findByUserName("admin") == null) {
val adminRole = roles.findByName("admin")!!
val adminUser = BackendUser("admin", adminRole
// some more data here
)
users.save(adminUser)
}
}
}
应用程序在启动和关闭时抛出异常:
org.hibernate.PersistentObjectException: detached entity passed to persist: my.package.name.user.UserRole
我在这里的理解是,adminRole
在从存储库中检索后立即处于分离状态。
- 为什么会分离?我曾假设方法上的 @Transactional 注释将确保一切都发生在相同的持久性上下文中,而这不应该发生。
- 我该如何防止这种情况发生?有没有办法不用删除级联选项
- 关于 spring/jpa 和 hibernate 如何协同工作是否有任何好的信息来源 - 到目前为止,我发现的任何东西都没有真正帮助我详细理解这些概念,以及 respositoryies 如何隐藏实体您在尝试阅读休眠时发现的管理和会话概念。
由于您在私有方法上使用了@Transactional,并且还从同一个方法中调用了一个方法class,因此没有事务,因此分离状态用于保存(see this)。 不确定您是否可以在 运行() 或此 class 上应用 @Transactional。 无论如何,也许您应该使用 public @Transactional 方法创建新的“服务”class,然后从您的 class.
调用此服务