1

我只是在学习 Scala 并尝试使用 Spring 创建不同的场景。

以下代码完美执行:

def insert(student: Student): Unit = {

  jdbcTemplate.update("INSERT INTO STUDENT (ID, FIRSTNAME, LASTNAME) VALUES(?,?,?)",
        new PreparedStatementSetter() {
          def setValues(ps: PreparedStatement) {
            ps.setString(1, student.id)
            ps.setString(2, student.firstName)
            ps.setString(3, student.lastName)
          }
        })
    }
  }

但是,当我尝试隐式创建 PreparedStatementSetter 时,我的 SQL 代码会失败。

我的隐含功能是:

implicit def preparedStatementSetterImplicit(student: Student) = {
  new PreparedStatementSetter() {
    def setValues(ps: PreparedStatement) {
      ps.setString(1, student.id)
      ps.setString(2, student.firstName)
      ps.setString(3, student.lastName)
    }
  } 
}

我正在尝试通过以下方式使用它:

def insert(student: Student): Unit = {

  jdbcTemplate.update("INSERT INTO STUDENT (ID, FIRSTNAME, LASTNAME) VALUES(?,?,?)",
                            student)
}

我的 SQL 插入失败,但出现以下异常:

Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [INSERT INTO STUDENT (ID, FIRSTNAME, LASTNAME) VALUES(?,?,?)]; nested exception is java.sql.SQLSyntaxErrorException: incompatible data type in conversion

我的隐式转换有什么问题?

4

2 回答 2

4

问题是编译器不需要进行隐式转换,因为 jdbcTemplate.update它有一个重载的类型签名,它只需要String并且Object...将匹配StringStudent不需要隐式转换。您可以像这样显式地执行此操作(我认为这对于代码的可读性更好):

  implicit class preparedStatementSetterImplicit(student: Student) {
    def toPreparedStatement() = {
      new PreparedStatementSetter() {
        def setValues(ps: PreparedStatement) {
          ps.setString(1, student.id)
          ps.setString(2, student.firstName)
          ps.setString(3, student.lastName)
        }
      }
    }
  }

 def insert(student: Student) {
            jdbcTemplate.update("INSERT INTO STUDENT (ID, FIRSTNAME, LASTNAME) VALUES(?,?,?)",
                            student.toPreparedStatement())
  }
于 2013-10-20T18:19:02.437 回答
1

您是否尝试过显式输入转换,例如:

implicit def student2pss(student: Student) : PreparedStatementSetter = {...}

仅当转换后的类型与预期类型完全匹配时才使用隐式转换(并且在没有显式键入的情况下,您的转换会返回匿名类型,而不是完全PreparedStatementSetter),所以我不确定转换是否正在使用。尝试添加println转换以查看它是否被解雇。

编辑: 要解决此问题,您可能需要创建自己的包装器JdbcTemplate并为其提供转换:

class JdbcTemplateWrapper(val template: JdbcTemplate) {
    def wrappedUpdate[DataType](statement: String, data: DataType)(implicit conv: DataType => PreparedStatementSetter) = {
        template.update(statement, conv(data))
    }
}
object JdbcTemplateWrapper {
    implicit def wrapJdbc(template: JdbcTemplate) = new JdbcTemplateWrapper(template)
}

在范围内,一条线

jdbcTemplate.customUpdate("INSERT INTO STUDENT (ID, FIRSTNAME, LASTNAME) VALUES(?,?,?)",
                        student)

将首先隐式转换jdbcTemplateJdbcTemplateWrapper(为了使其响应cusomUpdate然后隐式转换StudentPreparedStatementSetter.

于 2013-10-20T18:08:40.853 回答