[英]How to get Thread Safe in DAO design?
據我了解,使用此代碼可能會在更改用戶角色時,另一個用戶可以更改同一角色並始終贏得最后一個角色。 對於我們來說,甚至可以存儲一部分的一部分和另一部分的一部分。 由於DAO中有3個查詢,因此這是可能的。 我想獲得“ ThreadSafe”,在更改期間,其他用戶不能進行更改,否則將檢測到有人之前對其進行了更改。
我的想法是更改RoleManager中的方法。
理念:
public interface RoleManager {
static synchronized void EditRole(UserRoleBO editedObjet, UserRoleBO nonEditedObject);
這不適用於這種類型的設計(帶有接口)。
我的問題:
有沒有一種不改變設計即可解決問題的優雅方法?
補充說明:
告訴我代碼中是否有重大錯誤。
經理:
public class RoleManagerImpl implements RoleManager {
@Override
public void editRole(UserRoleBO editedObjet, UserRoleBO nonEditedObject) {
EditUserRole editUserRole = EditUserRole.Factory.createEditUserRole(nonEditedObject);
boolean hasChangedBeforeInDB = editUserRole.detectChanges();
if (hasChangedBeforeInDB) {
throw new ManagerException(ManagerException.TYPE.HASCHANGEDBEFOREINDB, null);
}
RoleDAO roleDAO = new RoleDAOImpl();
roleDAO.editRole(editedObjet);
}
}
DAO:
@Override
public int editRole(UserRoleBO role) {
Connection conn = null;
int status;
try {
//Set up connection
conn = ConnectionPool.getInstance().acquire();
DSLContext create = DSL.using(conn, SQLDialect.MARIADB);
//sql processing and return
status = create.executeUpdate(role.getRole());
EditUserRole editUserRole = EditUserRole.Factory.createEditUserRole(role);
editUserRole.detectChanges();
addPermission(editUserRole.getAddlist(), role.getRole());
deletePermissions(editUserRole.getDeleteList(), role.getRole());
}
// Error handling sql
catch (MappingException e) {
throw new DAOException(DAOException.TYPE.MAPPINGEXCEPTION, e);
}
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.DATAACCESSEXECPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNEXCEPTION, e);
} finally {
//Connection release handling
try{
if(conn != null) {
ConnectionPool.getInstance().release(conn);
}
}
// Error handling connection
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.RELEASECONNECTIONEXCEPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNRELEASECONNECTIONEXCEPTION, e);
}
}
//Return result
return status;
}
感謝您的幫助。
這只是一個可能的答案。 就我而言,我使用jooq和mariadb。
假設我們只有一個中央數據庫,則此解決方案有效。 在集群中,總是存在大腦分裂的問題。
發生的事情是我鎖定了行。 因此,如果下一個線程試圖鎖定它,則必須等待。 如果允許其繼續,則拋出異常HASCHANGEDBEFOREINDB。
請注意,您必須提交或回滾才能結束鎖定。
EditRole:
@Override
public int editRole(UserRoleBO editedRole ,UserRoleBO nonEditedRole) throws SQLException {
Connection conn = null;
int status;
try {
//Set up connection
conn = ConnectionPool.getInstance().acquire();
conn.setAutoCommit(false);
DSLContext create = DSL.using(conn, SQLDialect.MARIADB);
//lock rows
lockRowsOf(editedRole, conn);
EditUserRole editUserRole = EditUserRole.Factory.createEditUserRole(nonEditedRole);
boolean hasChangedBeforeInDB = editUserRole.detectChanges();
if (hasChangedBeforeInDB) {
throw new DAOException(DAOException.TYPE.HASCHANGEDBEFOREINDB, null);
}
EditUserRole editUserRole2 = EditUserRole.Factory.createEditUserRole(editedRole);
editUserRole2.detectChanges();
//sql processing and return
status = create.executeUpdate(editedRole.getRole());
addPermission(editUserRole2.getAddlist(), editedRole.getRole().getId(), conn);
deletePermissions(editUserRole2.getDeleteList(), editedRole.getRole(), conn);
conn.commit();
}
// Error handling sql
catch (MappingException e) {
conn.rollback();
throw new DAOException(DAOException.TYPE.MAPPINGEXCEPTION, e);
}
catch (DataAccessException e) {
conn.rollback();
throw new DAOException(DAOException.TYPE.DATAACCESSEXECPTION, e);
}
catch (Exception e) {
conn.rollback();
throw new DAOException(DAOException.TYPE.UNKOWNEXCEPTION, e);
} finally {
//Connection release handling
try{
if(conn != null) {
conn.setAutoCommit(true);
ConnectionPool.getInstance().release(conn);
}
}
// Error handling connection
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.RELEASECONNECTIONEXCEPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNRELEASECONNECTIONEXCEPTION, e);
}
}
//Return result
return status;
}
鎖:
@Override
public void lockRowsOf(UserRoleBO role, Connection conn) {
int status;
try {
DSLContext create = DSL.using(conn, SQLDialect.MARIADB);
//sql processing and return
status = create.select()
.from(AUTH_ROLE)
.where(AUTH_ROLE.ID.eq(role.getRole().getId()))
.forUpdate().execute();
status = create.select()
.from(AUTH_ROLE_PERMISSION)
.where(AUTH_ROLE_PERMISSION.ROLE_ID.eq(role.getRole().getId()))
.forUpdate().execute();
}
// Error handling sql
catch (MappingException e) {
throw new DAOException(DAOException.TYPE.MAPPINGEXCEPTION, e);
}
catch (DataAccessException e) {
throw new DAOException(DAOException.TYPE.DATAACCESSEXECPTION, e);
}
catch (Exception e) {
throw new DAOException(DAOException.TYPE.UNKOWNEXCEPTION, e);
} finally {
//Connection will still needed to buffer the delete and insert
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.