У меня есть структура ETL, которую я написал в Scala, и во имя удаления тех же операторов try/catch и закрытия для каждого SQL-запроса и обновления, которые я выполняю, я сделал эту черту что я смешиваю все мои SQL-соединения.Случаи с плавающей областью Scala не работают с подключениями JDBC
trait SqlConnection {
private val defaultHandling = (stmt: PreparedStatement) => stmt.executeUpdate()
protected val con: java.sql.Connection
final def executeSimpleUpdate(sql: String): Unit = executeUpdate(sql)(defaultHandling)
final def executeUpdate[T](sql: String)(statementHandling: PreparedStatement => T) = {
val stmt = con.prepareStatement(sql)
try { statementHandling(stmt) } finally { if (!stmt.isClosed) stmt.close() }
}
final def executeQuery[T](sql: String)(resultHandling: ResultSet => T) = {
val stmt = con.prepareStatement(sql)
try {
val rs = stmt.executeQuery()
try { resultHandling(rs) } finally { if (!rs.isClosed) rs.close() }
} finally { if (!stmt.isClosed) stmt.close() }
}
final def close() = con.close()
}
Однако, когда я запускаю его, ни одна из команд не выполняется. Я добавил println
s, чтобы попытаться выделить, какие строки или код были или не запускались, и это дало мне эту ошибку.
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1320)
at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1312)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4547)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4512)
at util.SqlConnection$class.executeQuery(Connection.scala:50)
Я предполагаю, что моя проблема здесь заключается в непонимании того, как Scala обрабатывает значения функций и когда функции выполняются.
Может ли кто-нибудь объяснить, что здесь происходит или что такое подобное решение? Может быть, использовать inlining?
Здесь не достаточно информации, чтобы решить вашу проблему. Как и где открывается соединение? Понятно, что к тому моменту, когда «prepareStatement» вызывается в соединении, он уже закрыт, поэтому вам нужно выяснить, как это произошло. Если соединение будет распространено в другом месте (что не будет хорошей идеей), это другой код, закрывающий его? – cmbaxter
Это не ваш вопрос, но обратите внимание, что закрытие 'Statement' закрывает' ResultSet', поэтому, если вы знаете, что закрываете 'Statement', вам не нужно закрывать' ResultSet' отдельно. Кроме того, я не вижу способа передать параметры запросам через ваш класс-оболочку. –