文档章节

解决spring jdbc中出现的java.io.NotSerializableException

cyper
 cyper
发布于 2012/09/29 10:46
字数 587
阅读 8644
收藏 0

今天学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

cyper

粉丝 58
博文 685
码字总数 143207
作品 0
武汉
前端工程师
私信 提问
kisso 3.6.10 发布,SSO 中间件

kisso 3.6.10 发布了, kisso = cookie sso,基于 Cookie 的 SSO 中间件,它是一把快速开发 java Web 登录系统(SSO)的瑞士军刀。目前功能有权限管理、api服务、oauth2认证、单点授权一体的...

青苗
2016/04/30
1K
3
eClipse import Spring之后出现的问题

你好,我的 eClipse 是 kepler 版的 , Spring 的下载网址是 https://github.com/spring-projects/spring-framework jdk 版本是 8 的 , java -version 指令显示版本号码是 1.8.0_05 我在 Spri......

Arthur1977
2014/07/12
1K
1
mysql中时间数据差14小时

问题 调试代码中,确定了出来的时间数据是准确了,没有出现差14小时情况,通过Spring hibernate jdbc这一路保存到mysql数据库中,就出现了14小时问题。 排查 mysql排查 到这里,基本上排除了...

亚林瓜子
2018/12/18
0
0
为什么越来越多的开发者选择使用Spring Boot?

一、Web应用开发背景 使用Java做Web应用开发已经有近20年的历史了,从最初的Servlet1.0一步步演化到现在如此多的框架、库以及整个生态系统。经过这么长时间的发展,Java作为一个成熟的语言,...

Ala6
2018/10/10
0
0
Spring Boot实战之基础回顾

本文作者: 吴伟祥 本文链接: https://wuweixiang.cn/2018/08/21/Spring-Boot实战之基础回顾/ 版权声明: 本博客所有文章除特别声明外均为原创,采用CC BY-NC-SA 4.0 许可协议。转载请在文章开...

吴伟祥
2018/08/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《1984》读后感作文4000字

《1984》读后感作文4000字: 新年的第一天,开始阅读Gorge Owell的政治寓言小说。以前阅读的是上译的董乐山的译本,也拜读过刘绍铭的译本,两人在翻译上各有千秋。董先生的译本显得有些压抑严...

原创小博客
30分钟前
4
0
Django集成Markdown编辑器【附源码】

专注内容写作的你一定不要错过markdown 简单介绍 markdown是一种标记语言,通过简单的标记语法可以使普通的文本内容具有一定的格式,使用非常简单,学习成本极低 目前各大Blog平台都已支持m...

运维咖啡吧
47分钟前
4
0
C++中虚函数的作用是什么?它应该怎么用呢?

C++中虚函数的作用: 1、简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。 2、实现多态性,多态性是将接口与实现进行分离。 3、当基类指针指向一个子类对象,通过这个指针调用子类...

天王盖地虎626
51分钟前
3
0
简单聊聊Linux学习经历

学习,是我们一生中都规避不了的一个话题,人的一生中都是在不断的学习,无论是功成名就的人士,还是一无是处的小混混,始终都处在一个不断学习的环境中,只是学习的内容千差万别,有的人是为...

linuxprobe16
52分钟前
3
0
面试之ssm粗略简答

说实在的,spring源码对我来说可能就是报错的时候会一个个点进去找错误源头,其他都是为了让自己学习大神们优秀的编程思想和理念(顺便面试的时候吹吹牛皮~) 这次zhjj就直接抛了一个范围很...

无极之岚
58分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部