文档章节

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

cyper
 cyper
发布于 2012/09/29 10:46
字数 587
阅读 8420
收藏 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
码字总数 143161
作品 0
武汉
前端工程师
Spring Boot实战之基础回顾

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

吴伟祥
08/21
0
0
tomcat的OutOfMemoryError解决方法

最近在熟悉一个开发了有几年的项目,需要把数据库从mysql移植到oracle,首先把jdbc的连接指向mysql,打包放到tomcat里面,可以跑起来,没有问题,可是当把jdbc连接指向oracle的时候,tomcat就...

光石头
2011/05/17
0
0
为什么越来越多的开发者选择使用Spring Boot?

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

Ala6
10/10
0
0
SpringBoot实战(四)之使用JDBC和Spring访问数据库

这里演示的是h2databse示例,所以简单的介绍普及下h2database相关知识 H2数据库是一个开源的关系型数据库。 H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个...

youcongtech
08/03
0
0
【小马哥】Spring Boot系列讲座

这里为大家推荐一个不错的Spring Boot系列讲座,讲师介绍如下: 小马哥,阿里巴巴技术专家,从事十余年Java EE 开发,国内微服务技术讲师。目前主要负责微服务技术推广、架构设计、基础设施、...

杜琪
03/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

阿里P8架构师深度概述分布式架构

简介 作为一名架构师,我们要专业,要能看懂代码,及时光着臂膀去机房,也能独挡一面!及时同事搞不定问题,或者撂挑子,你也能给老大一个坚定的眼神:不怕,有我在!还能在会议室上滔滔不绝...

java知识分子
13分钟前
0
0
zabbix利用自带的模板监控mysql数据库

zabbix利用自带的模板监控mysql数据库                                     作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 有些东...

linjin200
19分钟前
0
0
当刷新的Sandbox后,需要重新发布社区

当刷新的Sandbox后,需要重新发布社区 然后在登录页面设置中选择login/forgot password

在山的那边
20分钟前
0
0
Ubuntu 镜像文件下载

https://www.ubuntu.com/download/desktop

15834278076
23分钟前
0
0
解决php -v查看到版本于phpinfo()打印的版本不一致问题

一般造成这种原因可能是升级或多版本 用php -v 和phpinfo()查出来版本不一致,怎么解决呢 编辑/etc/profile文件在最后一行添加一个环境变量: export PATH="/usr/local/php/bin:$PATH" 最后保...

xiaogg
24分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部