2017-06-11 12 views
0

このコードでは、ユーザーロールを変更するときに、別のユーザーが同じロールを変更して常に最後に勝つことができます。 1つの部分と他の部分の部分を保存することも可能です。これは、DAOの3つのクエリのために可能です。変更中に別のユーザーが変更を加えることができない、または誰かがそれを以前に変更したことが検出される、「ThreadSafe」を取得したいと思います。DAOデザインでスレッドセーフを取得するには?

私の考えは、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; 
    } 

感謝。

+1

私は'トンをドンは、メソッドの同期がここに適用されると思います。通常、メモリ内の共有オブジェクトを扱うときには同期を使用しますが、データベースに格納された共有データを扱う場合は同期を使用します。データベースロックとトランザクションを使用する必要があります。 アプリケーションでは、独自のJVMを持つ異なるアプリケーションコンテナインスタンスで複数のインスタンスを実行できることに気づく必要があります。 – tsolakp

+0

@tsolakp多くのありがとうございます。あなたは完全に正しいです。独自のJVMにアプリケーションを実行する複数のサーバーが存在する可能性があります。あなたは私に必要な考えを与えました。データベースが1つしかないと仮定したときに動作するソリューションを投稿します。 – Van

答えて

0

これは単なる可能な答えです。私の場合、私はjooqとmariadbを使います。

私たちは1つの中央データベースしか持っていないと仮定して、この解決法が機能します。クラスタでは、常に分割された脳の問題があります。

何が起こるかは、私が行をロックすることです。したがって、次のスレッドがこれをロックしようとすると、彼は待たなければなりません。続行が許可されている場合は、例外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 
      } 
     } 
関連する問題