Je veux construire une classe CUSTOCLOSIBLE CODE> Autoclosable CODE>, afin que je puisse transformer ceci: dans la facilité p> Si cela nécessite d'analyser la trace de la pile à partir d'une nouvelle exception, c'est bon. La programmation plus facile aurait la peine de toucher la petite performance qui apporte. P> p> transaction code> serait le
autoclogeable code> ici et dans
close () code> Il engagerait ou retourne la transaction comme approprié. p> < P> Mais pour faire ce travail, je devrais détecter dans
transaction.close () code> si une exception s'est produite à l'intérieur du bloc d'essai ou complétée normalement. Est-ce possible du tout? P>
3 Réponses :
Le plus proche que je puisse arriver, il est toujours nécessaire de marquer le succès de la transaction manuellement comme la dernière instruction du bloc:
class Transaction implements AutoCloseable { private boolean rollback = true; public void success() { rollback = false; } public void close() { if (rollback) doRollback(); else doCommit(); // ⦠} } class Main { public static void main(String[] args) { try (Transaction t = new Transaction()) { doThings(); t.success(); } } }
Bien que mon code soit différent de la vôtre, j'ai eu un besoin similaire pour commettre automatiquement les transactions (la plupart) transactions et la restauration sur les erreurs.
La plupart du temps mon code est saupoudré de simples requêtes qui se font rouler automatiquement, comme ça : P>
try(Transaction t : database.beginReadOnlyTransaction()) { return t.selectUnique(Employee.class, "id=?", 200); } // implicit commit here
Le plus proche que j'ai pu obtenir est d'appeler explicitement commettre () et de supposer que n'importe quel code qui quitte le bloc de transaction sans le faire devrait être renvoyé. Ceci est cohérent avec les transactions dans d'autres langues. Pendant que vous pouvez oublier d'appeler commettre () (comme je le fais souvent), au moins cette partie du code est très probablement testée. Et, il est impossible d'oublier de retourner à l'exception, ce qui est moins susceptible d'avoir une couverture de test.
Ceci est similaire à l'idée de Millimoose de définir un drapeau: p> sauf que vous utilisez simplement l'état actif comme drapeau. Même quantité de code, aucun nouvel indicateur nécessaire. Cela suppose que toute transaction pour laquelle commit () n'a pas été explicitement appelée doit être renvoyée, ce qui a entraîné un code comme celui-ci: P> try (Transaction t = new Transaction()) {
doThings();
t.commit(); // marks the transaction as successful...
}
class Transaction implements AutoCloseable {
public void close() {
if (isActive())
doRollback();
}
...
}
Je pense que l'essai avec les ressources est spécifiquement destiné à gérer le cas où la configuration et le nettoyage d'une ressource se lancent eux-mêmes des exceptions, conduisant au redouté
enfin {essayer {if (ressource! = Null) {ressource.frose () ... code> bloc. Ce n'est pas censé être les gestionnaires de contexte de Python.
@Inderdial peut-être, mais s'il est possible (que cette question montrait, espérons-le), je ne suis pas contre les abuser d'un tel but.
Par "précisément", je voulais dire que j'ai écrémé la spécification et aussi loin que possible, tout ce qui se passe est que le bytecode correspondant aux blocs de configuration / nettoyage est généré, avec les points uniquement i> points sur lesquels vous pouvez accrocher En étant l'initialiseur et la mise en œuvre de
autoclotionable.Close code>, qui ne accepte aucun paramètre d'exception.