I get "detached entity passed to persist", but I do not understand, how the object in question can be in a detached state.
Here is some context first.
two JpaRepository
s for each users and roles:
@Repository
interface RoleRepository : JpaRepository<UserRole, Long> {
fun findByName(name: String): UserRole?
}
@Repository
interface BackendUserRepository : JpaRepository<BackendUser, Long> {
fun findByUserName(name: String): BackendUser?
}
The BackendUser
entity - besides the name - has several fields that should not be related to this question, the foreign field role comes from its base class:
abstract class User(
@ManyToOne(fetch = FetchType.LAZY, cascade = arrayOf(CascadeType.ALL), optional = false)
@JoinColumn(referencedColumnName = "name", nullable = false)
var role: UserRole
) : UserDetails {
// ...
}
On application startup, I want to ensure that an admin user exists in this 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)
}
}
}
The application throws an exception on startup and shuts down:
org.hibernate.PersistentObjectException: detached entity passed to persist: my.package.name.user.UserRole
The way I understand it here is, that adminRole
is in a detached state straight after it was retrieved from the repository.
Since you have @Transactional on private method and also one called from the same class, there is no transaction and therefore detached state for save (see this). Not sure if you can apply @Transactional on run() or this class. Anyway, maybe you should create new "Service" class with public @Transactional method, and than call this service from your class.