I was wondering what is the correct way to organize my class hierarchy in the following situation.
I wanted to build an abstraction around postgresql advisory lock.
Note just for context: An advisory lock is a lock that you can obtain at a session or transaction level. Postgres handle all the complexity for you.
The code that I've written so far is something like
interface DBLockService
interface SessionLockService : DBLockService {
fun acquire(id: Long)
fun unlock(id: Long): Boolean
}
interface TransactionalLockService : DBLockService {
fun txAcquire(id: Long)
}
abstract class BaseDBLockService(protected val entityManager: EntityManager): DBLockService {
protected fun executeAcquire(preparedStatement: String, id: Long) {
executeAcquire<Any>(preparedStatement, id)
}
protected inline fun <reified T> executeAcquire(preparedStatement: String, id: Long) =
entityManager
.createNativeQuery(preparedStatement, T::class.java)
.setParameter("id", id)
.singleResult as T
}
@Component
class LockServiceImpl(
entityManager: EntityManager
) : BaseDBLockService(entityManager),
SessionLockService {
companion object {
const val acquireStatement = "SELECT pg_advisory_lock(:id)"
const val unlockStatement = "SELECT pg_advisory_unlock(:id)"
}
override fun acquire(id: Long) {
executeAcquire(acquireStatement, id)
}
override fun unlock(id: Long) =
executeAcquire<Boolean>(unlockStatement, id)
}
@Component
class TransactionalLockServiceImpl(
entityManager: EntityManager
) : BaseDBLockService(entityManager),
TransactionalLockService {
// very similar implementation
}
Looking at this code there is something that tell's me that there is something wrong:
DBLockService
is a bit useless interface, there is no method- Are
SessionLockService
andTransactionalLockService
just an implementation detail? Is it correct that there is a different interface for every "type" of lock?
But at the same time, if I remove the DBLockService
seems very odd to me that there are 2 interfaces (SessionLockService
and TransactionalLockService
) with very similar context that are not related in any way.
Moreover, removing DBLockService
, I'll have the 2 implementations (LockServiceImpl
and TransactionalLockServiceImpl
) that extends from the abstract class BaseDBLockService
to implement these 2 interfaces but at the same time the abstract class is not related to them.
What to you think?
Thanks
Aucun commentaire:
Enregistrer un commentaire