2017-08-12 10 views
3

En Java 7 est-il possible de passer la méthode en tant que paramètre.Java 7 passe méthode en tant que paramètre pour SQL statique Deadlock vérifier

La méthode serait invoquée et serait encapsulée dans un do while pour vérifier les blocages SQL et réessayer. J'essaye de faire une manière générique de manipuler des deadlocks quand il y a un verrou sur la table, car il y a actuellement des milliers d'insertions et de mises à jour pour répliquer ceci. Actuellement, il ne rechercherait que SQLException mais cela pourrait être changé en getErrorCode de SQLException et target ER_LOCK_DEADLOCK.

Le code ci-dessous est juste un exemple de ce que je suis en train de réaliser:

public void Object1Insert(Object1 object1){ 
    genericSQLRetry(insertObject1(object1)); 
} 

public void Object2Insert(Object2 object2){ 
    genericSQLRetry(insertObject2(object2)); 
} 

public void genericSQLRetry({method}){ 
    int retries = 5; 
    boolean isException = false; 
    do{ 
    try { 
     isException = false; 
     retries--; 
     //Invoke method 
     {method} 
    }catch (SQLException e){ 
     isException = true; 
    } 

    if (isException & retries > 0){ 
     //getRandomSleep would be between 750-1250ms. This is to stop multiple retries at the same time. 
     Thread.sleep(getRandomSleep()); 
    } 
    }while (isException == true && retries > 0); 
} 

Répondre

2

En Java 7 est-il possible passer la méthode comme paramater.

Non. C'est pourquoi Java 8 ajoute des lambdas (y compris les références de méthode) et des interfaces fonctionnelles.

Mais vous pouvez définir la méthode dans une interface, implémenter cette interface dans la ou les classes appelantes (peut-être anonymes instanciées localement), accepter cette interface dans genericSQLRetry et appeler la méthode sur l'instance que vous recevez.

Dans votre cas, vous pouvez réutiliser Runnable (qui est ce qu'ils ont fait en Java 8 pour lambdas sans paramètres et aucune valeur de retour), et:

public void Object1Insert(final Object1 object1) { 
    genericSQLRetry(new Runnable { 
     public void run() { 
      insertObject1(object1); 
     } 
    }); 
} 

public void Object2Insert(Object2 object2) { 
    genericSQLRetry(new Runnable { 
     public void run() { 
      insertObject2(object2); 
     } 
    }); 
} 

public void genericSQLRetry(Runnable retryable) { 
    int retries = 5; 
    boolean isException = false; 
    do { 
     try { 
      isException = false; 
      retries--; 
      //Invoke method 
      retryable.run(); 
     } 
     catch (SQLException e) { 
      isException = true; 
     } 

     if (isException & retries > 0) { 
      //getRandomSleep would be between 750-1250ms. This is to stop multiple retries at the same time. 
      Thread.sleep(getRandomSleep()); 
     } 
    } while (isException == true && retries > 0); 
} 

Personnellement, bien que, je préfère ma propre interface qui est plus clair sémantiquement:

interface Retryable { 
    void retry() { 
    } 
} 

puis utilisez Retryable au lieu de Runnable.

1

Oui, vous pouvez passer une méthode en paramètre dans une certaine mesure si vous utilisez la réflexion.

Vous passeriez une chaîne avec le nom de la méthode correcte et utiliser

Method method = this.getClass().getDeclaredMethod("methodName", new Class[]}); 

puis à utiliser:

method.invoke(object) 

Plus d'informations sur la réflexion se trouvent here et here y compris pourquoi vous devriez avoid using it .

+0

Oui, je connaissais la réflexion et j'essayais de l'éviter pour ces raisons. Merci. –

+0

Vous êtes les bienvenus. Avez-vous essayé d'utiliser JTA (Java Transaction API) pour faire face à un blocage? Cela pourrait vous aider. – Pfeiffer