1

Spring 3.2 のドキュメント ( http://static.springsource.org/spring/docs/3.2. x/spring-framework-reference/html/jdbc.html ):

public class JdbcActorDao implements ActorDao {
    private JdbcTemplate jdbcTemplate;
    private SimpleJdbcCall procReadActor;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.procReadActor =
                new SimpleJdbcCall(dataSource)
                        .withProcedureName("read_actor");
    }

    public Actor readActor(Long id) {
        SqlParameterSource in = new MapSqlParameterSource()
                .addValue("in_id", id);
        Map out = procReadActor.execute(in);
        Actor actor = new Actor();
        actor.setId(id);
        actor.setFirstName((String) out.get("out_first_name"));
        actor.setLastName((String) out.get("out_last_name"));
        actor.setBirthDate((Date) out.get("out_birth_date"));
        return actor;
    }

    //  ... additional methods
}

私の実装は次のとおりです。

@Repository
public class ObjectDao {

    private JdbcTemplate jdbcTemplate;

    @Value("${db.sp.getObject}")
    private String spName;

    private SimpleJdbcCall jdbcCall;


    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.jdbcCall=
                new SimpleJdbcCall(dataSource)
        .withProcedureName(spName);
    }

    public SQLXML getDbObjectById(Integer id) {

        SqlParameterSource in = new MapSqlParameterSource()
                .addValue("objectId", id, Types.INTEGER);


        Map<String, Object> out = jdbcCall.execute(in);

        return (SQLXML) out.get("OutputXML");
    }

}

他のデータベース トランザクションで接続パラメーターをテストしたところ、これらは成功しましたが、XML 変数を使用する出力パラメーターを読み取ろうとすると、以下のように BadSqlGrammarException が表示されます。

EXECEPTION

    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

ROOT CAUSE

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call spXML_Wrapper(?, ?, ?)}]; nested exception is  c om  .microsoft.sqlserver.jdbc.SQLServerException: Implicit conversion from data type xml to nvarchar(max) is not allowed. Use the CONVERT function to run this query.
    org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:98)
    org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1036)
    org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1070)
    org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:387)
    org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:350)
    org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:181)
    com.test.dao.ObjectDao.getDbObjectById(InvoiceDaoImpl.java:59)
    ........

ROOT CAUSE 

com.microsoft.sqlserver.jdbc.SQLServerException: Implicit conversion from data type xml to nvarchar(max) is not allowed. Use the CONVERT function to run this query.
    com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
    com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
    com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
    com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
    com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
    com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:332)
    org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
    org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
    org.springframework.jdbc.core.JdbcTemplate$6.doInCallableStatement(JdbcTemplate.java:1072)
    org.springframework.jdbc.core.JdbcTemplate$6.doInCallableStatement(JdbcTemplate.java:1070)
    org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1020)
    org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1070)
    org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:387)
    org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:350)
    org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:181)
    com.test.dao.ObjectDao.getDbObjectById(InvoiceDaoImpl.java:59)
    .......

ストアド プロシージャ自体が問題なく動作することを確認しました。正常に実行されます。このようなエラーの経験がある人や、Spring フレームワークを使用してストアド プロシージャから XML 出力を読み取るための代替提案がある人はいますか?

他の情報:

春 3.2

トムキャット 7.0

SQL Server 用 Microsoft JDBC ドライバー 4.0

ご協力いただきありがとうございます

4

1 に答える 1

1

これは調べていないので単なる理論ですが、私の推測では、SQL Server JDBC ドライバーで使用される XML 型は、.NET で使用される標準のデータ型の値を使用していませんjava.sql.Types

私ならResultSetMetaData.getColumnType()、ストアド プロシージャから返されるデータ型の値を出力する単純なスタンドアロン JDBC プログラムを作成します。その整数が にリストされていない場合、java.sql.TypesSpring がそれを文字列値にデフォルト設定している可能性があり、データ型推論の処理方法をオーバーライドする方法を見つける必要があります。

SimpleJdbcCall を使用してこれを実現できるとは思いません。残念ながら、JdbcTemplate の使用にフォールバックする必要があると思います。ストアド プロシージャでの Spring のデータ型の処理は、かなり制限されているようです。

于 2013-06-11T21:03:12.467 に答える