2014-05-27 8 views
0

У меня есть структура 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?

+1

Здесь не достаточно информации, чтобы решить вашу проблему. Как и где открывается соединение? Понятно, что к тому моменту, когда «prepareStatement» вызывается в соединении, он уже закрыт, поэтому вам нужно выяснить, как это произошло. Если соединение будет распространено в другом месте (что не будет хорошей идеей), это другой код, закрывающий его? – cmbaxter

+0

Это не ваш вопрос, но обратите внимание, что закрытие 'Statement' закрывает' ResultSet', поэтому, если вы знаете, что закрываете 'Statement', вам не нужно закрывать' ResultSet' отдельно. Кроме того, я не вижу способа передать параметры запросам через ваш класс-оболочку. –

ответ

0

Не держите свое соединение в качестве поля в своем классе. Оберните операции с базой данных в функции, которая открывает и закрывает соединение для вас. Попробуйте следующее:

private def withConnection[A](f: Connection => A): A = { 
    val con = JDBC.giveMeAConnection()// Do whatever you want to open a connection 
    val result = f(con) 
    con.close() 
    result 
} 

final def executeQuery[T](sql: String)(resultHandling: ResultSet => T) = withConnection { conn => 
    // Use conn as you wish here. 
} 
+0

Я на самом деле решил это, и это было нечто совершенно несвязанное, но спасибо за вклад. –

+0

@ EricHartsuyker приятно слышать. Тем не менее, это лучший стиль для обработки доступа к базе данных таким образом. – DCKing