解决spring jdbc中出现的java.io.NotSerializableException
博客专区 > cyper 的博客 > 博客详情
解决spring jdbc中出现的java.io.NotSerializableException
cyper 发表于5年前
解决spring jdbc中出现的java.io.NotSerializableException
  • 发表于 5年前
  • 阅读 7935
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

今天学spring3的jdbc,写了这么段代码

public Hello createHello(final Hello hello) {
        final String sql = "insert into crud_hello(name,age,money,at_work,icon,introduce,create_date)"
                + " values (?,?,?,?,?,?,now())";
        
        //Caused by: java.io.NotSerializableException: smartcrud.spring.models.crud.HelloDaoJdbcImpl$1
        //at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
        //at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        //at com.mysql.jdbc.PreparedStatement.setSerializableObject(PreparedStatement.java:4267)
        
//        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(sql, new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                PreparedStatement ps = con.prepareStatement(sql);
                int z = 0;
                ps.setString(++z, hello.getName());
                ps.setInt(++z, hello.getAge());
                ps.setDouble(++z, hello.getMoney());
                ps.setBoolean(++z, hello.isAtWork());
                ps.setBytes(++z, hello.getIcon());
                ps.setString(++z, hello.getIntroduce());
                return ps;
            }
        }/*, keyHolder*/);
        
//        hello.setId(keyHolder.getKey().longValue());
        
        /*
        jdbcTemplate.update(sql, new PreparedStatementSetter(){
            @Override
            public void setValues(PreparedStatement ps) throws SQLException {
                int z = 0;
                ps.setString(++z, hello.getName());
                ps.setInt(++z, hello.getAge());
                ps.setDouble(++z, hello.getMoney());
                ps.setBoolean(++z, hello.isAtWork());
                ps.setBytes(++z, hello.getIcon());
                ps.setString(++z, hello.getIntroduce());
            }});*/
        
        return hello;
    }

 

结果运行时出现如下错误

 org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [insert into crud_hello(name,age,money,at_work,icon,introduce,create_date) values (?,?,?,?,?,?,now())]; Invalid argument value: java.io.NotSerializableException; nested exception is java.sql.SQLException: Invalid argument value: java.io.NotSerializableException
    org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:107)
    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:603)
    org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:812)
    org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:868)
    org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:876)
    smartcrud.spring.models.crud.HelloDaoJdbcImpl.createHello(HelloDaoJdbcImpl.java:32)

为啥用PreparedStatementCreator就不可以,用下面的PreparedStatementSetter就没有问题。

看起来是XX没有序列化,可是我的实体Hello绝对是实现了Serializable接口的,各种搜索无果,今天爬起来,决定要跟踪一下到底哪儿出问题了。

在log4j.properties加入如下配置:
log4j.logger.org.springframework.jdbc=TRACE

观察到

[09-29 10:33:16 DEBUG] Executing prepared SQL update
[09-29 10:33:16 DEBUG] Executing prepared SQL statement [insert into crud_hello(name,age,money,at_work,icon,introduce,create_date) values (?,?,?,?,?,?,now())]
[09-29 10:33:17 DEBUG] Fetching JDBC Connection from DataSource
[09-29 10:33:17 TRACE] Setting SQL statement parameter value: column index 1, parameter value [smartcrud.spring.models.crud.HelloDaoJdbcImpl$1@12000a5], value class [smartcrud.spring.models.crud.HelloDaoJdbcImpl$1], SQL type unknown
[09-29 10:33:17 DEBUG] Returning JDBC Connection to DataSource

说的是第一个?占位符的value设置成了smartcrud.spring.models.crud.HelloDaoJdbcImpl$1,类型不识别。。可是我明明设置的
     ps.setString(++z, hello.getName());

是个String类型的,怎么会不识别呢。乍一看去没有道理,从编译的后的class文件中找到了smartcrud.spring.models.crud.HelloDaoJdbcImpl$1这个东西,

class 1
  implements PreparedStatementCreator,
OH,才恍然大悟,我的API用错了。
我用的是jdbcTemplate.update(sql,new PreparedStatementCreator()),

第二个参数PreparedStatementCreator默认成了sql的第1个占位符的值,正确的写法是
jdbcTemplate.update(new PreparedStatementCreator())

 修正后的代码如下:
 

@Repository
public class HelloDaoJdbcImpl implements HelloDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Hello createHello(final Hello hello) {
        final String sql = "insert into crud_hello(name,age,money,at_work,icon,introduce,create_date)"
                + " values (?,?,?,?,?,?,now())";
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(/*sql, */new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                PreparedStatement ps = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
                int z = 0;
                ps.setString(++z, hello.getName());
                ps.setInt(++z, hello.getAge());
                ps.setDouble(++z, hello.getMoney());
                ps.setBoolean(++z, hello.isAtWork());
                ps.setBytes(++z, hello.getIcon());
                ps.setString(++z, hello.getIntroduce());
                return ps;
            }
        }, keyHolder);
        hello.setId(keyHolder.getKey().longValue());
        return hello;
    }

}

 

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
cyper
粉丝 56
博文 619
码字总数 143069
×
cyper
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: