正确的类层次



我想知道在以下情况下组织我的类层次结构的正确方法是什么。
我想围绕postgresql的建议锁构建一个抽象。

仅供参考:建议锁是可以在会话中获得的锁。事务或的水平。Postgres为你处理所有的复杂性。

到目前为止我写的代码类似于
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
}

看看这段代码,有一些东西告诉我有问题:

  • DBLockService是一个有点没用的接口,没有方法
  • SessionLockServiceTransactionalLockService只是一个实现细节吗?每种"类型"都有不同的界面,对吗?锁吗?

但同时,如果我删除DBLockService对我来说似乎很奇怪,有两个接口(SessionLockServiceTransactionalLockService)具有非常相似的上下文,它们以任何方式都不相关。
此外,删除DBLockService,我将有两个实现(LockServiceImplTransactionalLockServiceImpl),从抽象类BaseDBLockService扩展到实现这两个接口,但同时抽象类与它们无关。

你觉得呢?


谢谢

更新

根据要求,我将添加一个真实案例场景的示例


@Service
class SomethingService(private val lockService: TransactionalLockService){

@Transactional
fun aMethod(entityId: Long){
lockService.txAcquire(entityId)
//code to be synchronized or there will be problems
}
}

我想注入一个类的通用LockService,但我找不到一种方法来抽象,因为imho一个锁,消失事务结束后的锁不同于与数据库连接关闭后消失的锁(会话锁),也不同于需要自动解锁的锁。
可能有很多锁的其他实现,例如TimeoutLock在一段时间后删除锁。
但是我想不出如何将这些实现细节与Lock的一般概念分开。

好的,谢谢你的例子。我仍然觉得把你想要实现的东西称为Service有点奇怪。我可能会称之为Strategy,但这并不是真正的重要。这只是一个语义偏好。

无论如何,我要做的可能是如下所示(未经测试/伪代码):
interface LockService {
Boolean acquire(Long id);
Boolean unlock(Long id);
}
abstract class BaseLockService
implements LockService {
protected EntityManager entityManager;

BaseLockService(EntityManager entityManager) {
this.entityManager = entityManager;
}

protected Boolean executeAcquire(String preparedStatement, Long id) {
// your generic implementation
}
}
class SessionLockService
extends BaseLockService {

private static class Statements {
static final String acquireStatement = "...";
static final String unlockStatement = "...";
}

SessionLockService(EntityManager entityManager) {
super(entityManager);
}

@Override
Boolean acquire(Long id) {
return executeAcquire(Statements.acquireStatement, id);
}

@Override
Boolean unlock(Long id) {
return executeAcquire(Statements.unlockStatement, id);
}
}
class TransactionalLockService
extends BaseLockService {

private static class Statements {
static final String acquireStatement = "...";
}

TransactionalLockService(EntityManager entityManager) {
super(entityManager);
}

@Override
Boolean acquire(Long id) {
return executeAcquire(Statements.acquireStatement, id);
}

@Override
Boolean unlock(Long id) {
// simply return true
return true;

// or if there's some Postgres or EntityManager mechanism to find out if the transaction is still active:
return !entityManager.isInTransaction(id);
}
}
class SomeService {
private final LockService lockService;
SomeService(LockService lockService) {
this.lockService = lockService;
}

void aMethod(Long entityId) {
if(!lockService.acquire(entityId)) {
throw new SomeException();
}

// do code that needs lock

if(!lockService.unlock(entityId)) {
throw new SomeException();
}
}
}

所以基本上,I使用一个通用接口,只是使TransactionalLockService.unlock()成为一个总是返回true的无操作函数,或者,如果可以实现,更可取的是:返回一些探测机制的结果,以找出与id的事务是否正确结束。

另一个想法是有一个Lock接口,LockService返回(非常简短的例子):

interface Lock {
Boolean unlock();
}
interface LockService {
Lock acquire(Long id);
}
class TransactionalLock 
implements Lock {
private Long id;
TransactionalLock(Long id) {
this.id = id;
}
@Override
Boolean unlock() {
// again, either simply return true
return true;
// ...or some result that verifies the transaction has ended
return verifyTransactionHasEnded(id);
}
}
class SomeService {
private final LockService lockService;
SomeService(LockService lockService) {
this.lockService = lockService;
}

void aMethod(Long entityId) {
Lock lock = lockService.acquire(entityId);
if(lock == null) {
throw new SomeException();
}

// do code that needs lock

if(!lock.unlock()) {
throw new SomeException();
}
}
}

…等。,但这可能会变得非常复杂,因为Lock的实现需要自己的机制来解锁自己。

这可能还不是你想要的,但希望它能给你一些想法。

相关内容

  • 没有找到相关文章

最新更新