2012-09-11 15 views
5

Estoy tratando de evitar variables mutables, pero el problema es que tengo que acceder a un val que necesito inicializar dentro del try (es una operación db que migth fail) y necesito que var en el bloque finallyscala: cómo evitar las mutables dentro de try catch blocks

he intentado con varias alternativas:

declarando el val dentro del bloque try

try { 
    val resultSet = SQL(sql).resultSet 
    return ColumnInfo(resultSet.getMetaData) 
} catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
} finally { 
    resultSet.close 
} 

error: not found: value resultSet 

declarando la val fuera del bloque try sin inicializarla

val resultSet: java.sql.ResultSet 
try { 
    resultSet = SQL(sql).resultSet 
    return ColumnInfo(resultSet.getMetaData) 
} catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
} finally { 
    resultSet.close 
} 

error: only classes can have declared but undefined members 

utilizando un var, que parece funcionar

var resultSet: java.sql.ResultSet = null 
try { 
    resultSet = SQL(sql).resultSet 
    return ColumnInfo(resultSet.getMetaData) 
} catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
} finally { 
    resultSet.close 
} 

y finalmente anidación bloque try-catch, que parece bastante sucio

try { 
    val resultSet = SQL(sql).resultSet 
    try { 
    return ColumnInfo(resultSet.getMetaData) 
    } catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
    } finally { 
    resultSet.close 
    } 
} catch { 
    case e => throw new ColumnInfoException("Error opening resultSet") 
} 

¿Hay algún método mejor que puedo tomar para evitar usar vars y anidar bloques try-catch?

Respuesta

0

Deshacerse del primer bloque catch:

try { 
    val resultSet = SQL(sql).resultSet 
    try { 
    ColumnInfo(resultSet.getMetaData) 
    } finally { 
    resultSet.close 
    } 
} catch { 
    case e => throw new ColumnInfoException("Error opening resultSet") 
} 
+0

¿Desea explicar el voto negativo? – nilskp

+0

la segunda captura también atrapará cualquier excepción desde el primer intento, ¿verdad? (upvoted, porque mejora mi propia versión ...) – opensas

+0

Sí, cerrará el conjunto de resultados, pero dejará la captura en el bloque try externo. – nilskp

3
import scala.util.control.Exception._ 

allCatch.either(SQL(sql).resultSet).right.flatMap{ resultSet => 
    val ans = allCatch.either(ColumnInfo(resultSet.getMetaData)) 
    resultSet.close 
    ans 
}.fold(e => throw e, identity) 

o puede omitir el fold y mantener la (s) excepción (es) empaquetada (s) en Left.

1

En Scala, try bloque es an expression. En su caso, puede evaluar a una tupla que contenga tanto val s:

val res: (java.sql.ResultSet, ColumnInfo) = try { 
    val rs = SQL(sql).resultSet 
    (rs, ColumnInfo(rs.getMetaData)) 
} catch { 
    case _: Throwable => throw new Exception("Error getting metadata") 
} finally { 
    res._1.close 
} 
val columnInfo = res._2