文档章节

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

cyper
 cyper
发布于 2012/09/29 10:46
字数 587
阅读 8224
收藏 0
点赞 0
评论 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
武汉
前端工程师
tomcat的OutOfMemoryError解决方法

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

光石头
2011/05/17
0
0
spring oxm入门(包含demo)

O/X Mapper 是什么? Spring 3.0 的一个新特性是 O/X Mapper。O/X 映射器这个概念并不新鲜,O 代表 Object,X 代表 XML。它的目的是在 Java 对象(几乎总是一个 plain old Java object,或简...

疯狂的兔子
2014/09/09
0
0
【小马哥】Spring Boot系列讲座

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

杜琪
03/02
0
0
使用Spring MVC 的 @RequestBody 映射json请求参数时报异常问题

使用Spring MVC 的 @RequestBody 映射json请求参数时报“The request sent by the client was syntactically incorrect.”异常解决方案 最近工作中开发RESTful接口需要处理客户端上传的json,...

Tek_Eternal
2015/03/01
0
3
基于可靠消息方案的分布式事务(二):Java中的事务

前言:在上一篇文章 基于可靠消息方案的分布式事务:Lottor介绍 中介绍了常见的分布式事务的解决方案以及笔者基于可靠消息方案实现的分布式事务组件Lottor的原理,并展示了应用的控制台管理。...

aoho
06/01
0
0
Spring MVC 使用 JNDI 配置的DataSource

稍微看了下,Spring 中JNDI 的使用,弄了个小例子。有很多不完备的地方,以后慢慢看,再改吧。 <一> 技术使用 Spring MVC JDBC Template Maven JNDI <二> 一些配置 Maven POM 配置 spring-c...

平江夜弹
2015/06/29
0
0
内存溢出之Tomcat内存配置

设置Tomcat启动的初始内存其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置 三、实例,以下给出1G内存环境下java jv...

挨踢精英
2015/03/18
0
0
Java高级程序员面试大纲——错过了金三,你还要错过银四吗

跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽。切不可跟风,看到同事一个个都走了,自己也盲目的开始面试起来(期间也没有准备充分),到底是因为技术原因(影响自己...

Java高级架构
04/27
0
0
对JDBC的支持 之 7.1 概述

概述 JDBC回顾 传统应用程序开发中,进行JDBC编程是相当痛苦的,如下所示: //cn.javass.spring.chapter7. TraditionalJdbcTest @Test public void test() throws Exception { Connection co...

heroShane
2014/02/27
0
0
java面试必备之ThreadLocal

按照传统的经验,如果某个对象是非线程安全的,在多线程环境下对象的访问需要采用synchronized进行同步。但是模板类并未采用线程同步机制,因为线程同步会降低系统的并发性能,此外代码同步解...

编程老司机
05/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

轻松搭建svn版本管理工具+svnmanager管理客户端

前面的文章有写过svn版本管理工具的安装是基于svn的安装包进行安装,对于svn与apache的结合还得下svn和apache的模块进行结合过程比较繁琐,今天来介绍下通过centos的yum来安装svn能够快速安装...

javazyw
16分钟前
0
0
keepalived配置高可用集群

Linux集群概述 根据功能划分为两大类:高可用和负载均衡 高可用集群通常为两台服务器,一台工作,另外一台作为冗余,当提供服务的机器宕机,冗余将接替继续提供服务 实现高可用的开源软件有:...

TaoXu
21分钟前
0
0
mysql联表批处理操作

1 概述 mysql中的单表增删改查操作,可以说是基本中的基本. 实际工作中,常常会遇到一些基本用法难以处理的数据操作,譬如遇到主从表甚至多级关联表的情况(如一些历史问题数据的批量处理),考虑到...

社哥
24分钟前
0
0
IntelliJ IDEA 详细图解最常用的配置,适合刚刚用的新人。

刚刚使用IntelliJ IDEA 编辑器的时候,会有很多设置,会方便以后的开发,磨刀不误砍柴工。 比如:设置文件字体大小,代码自动完成提示,版本管理,本地代码历史,自动导入包,修改注释,修改...

kim_o
38分钟前
0
0
Google Java编程风格指南

目录 前言 源文件基础 源文件结构 格式 命名约定 编程实践 Javadoc 后记 前言 这份文档是Google Java编程风格规范的完整定义。当且仅当一个Java源文件符合此文档中的规则, 我们才认为它符合...

niithub
41分钟前
0
0
java.net.MalformedURLException异常说明

1.异常片段 Java代码中,在进行URL url = new URL(urllink)操作时,提示以下异常信息,该类异常主要问题出在参数urllink上面。 异常片段1 java.net.MalformedURLException at java.ne...

lqlm
41分钟前
1
0
CentOS7修改mysql5.6字符集

解决办法:CentOS7下修改MySQL数据库字符编码为UTF-8,UTF-8包含全世界所有国家所需要的字符集,是国际编码。 具体操作如下: 1.进入MySQL [root@tianqi-01 ~]# mysql -uroot -p Enter passw...

河图再现
42分钟前
0
0
DevExpress v18.1新版亮点——WPF篇(一)

用户界面套包DevExpress v18.1日前终于正式发布,本站将以连载的形式为大家介绍各版本新增内容。本文将介绍了DevExpress WPF v18.1 的新功能,快来下载试用新版本!点击下载>> Accordion Co...

Miss_Hello_World
45分钟前
0
0
Rancher 2.0集群与工作负载告警

Rancher 2.0操作指南。本文将step by step演示如何使用Rancher 2.0中集成的告警功能,包括设置通知程序、设置集群级别以及工作负载级别的告警。 在Rancher 1.x时期,告警功能是很多Rancher用...

RancherLabs
50分钟前
1
0
Python中字符串拼接的N中方法

python拼接字符串一般有以下几种方法: ①直接通过(+)操作符拼接 s = 'Hello'+' '+'World'+'!'print(s) 输出结果:Hello World! 使用这种方式进行字符串连接的操作效率低下,因为python中...

木头释然
51分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部