欢迎来到Doc100.Net免费学习资源知识分享平台!
您的位置:首页 > 程序异常 >

公交开车人解决psqlexception

更新时间: 2014-01-05 02:06:58 责任编辑: Author_N1

 

公交司机解决PSQLException

最近遇到了一个bug,是关于JPA语句的问题,其实代码很简单,就是使用NamedQuery数据库中符合条件的数据进行更新操作,代码如下(其实不想贴代码) 

@NamedQuery(name = "customer.updateSentToBusinessCheckByCustomerIds", 
query = "update Customer as c set c.sentToBusinessCheck = true where c.id in :customerIds")})


很简单就是in 后面传递一个list的参数,根据这个list当中的数值进行条件更新,因为数据量小的时候比如几百、几千还是没有问题的,但是一旦list中的数据变大之后,准确的说是超过三万多就不行了(你知道为什么是三万多吗,或者这么问你知道为什么数值是32767吗),生产上我们这里的list是五万多记录,于是会报如下错误(其实真的不想贴代码):

Internal Exception: org.postgresql.util.PSQLException: An I/O error occured while sending to the backend.


Error Code: 0
Call: UPDATE CUSTOMER SET SENTTOBUSINESSCHECK = ?, ENTITYVERSION = (ENTITYVERSION + ?) 
WHERE
 (ID IN (?,?,?,?,?,?,?,?,?,?......)bind => [60102 parameters bound]

最快速的解决问题的办法——Google(你知道为啥不用百度吗?),从网上找到一篇文章(轻击这里)重点引用如下。(请注意,具体的解决办法不重要,重要的是作者解决问题的思路和行动意识。) 

Not a very concrete message, right? When I first saw this exception I waskind of baffled and disaffected. But after narrowing down the problem in adebug session and looking at the PostgreSQL JDBCdriver’s source code the cause was obvious: the PostgreSQLclient/backend protocol dictates that the number of parameters be send from theclient to the Postgres backend as a 2 byte integer (aaah, now the above message actually makes sense). You’llfind details of the protocol here if you’re brave (my 2-byte friend is definedin the Parse message). 

这下明白了,出现异常的原始是因为JPA实现的时候允许的最大的参数数目是有上限的(废话~)。文章最后也说了解决办法,一旦当参数超过上限这个时候就应该把参数分别传递,在这里就是将list分别传递到JPA语句中进行更新操作。最终代码如下(真的,真的不想贴代码) 

    ......
        emMain.createNamedQuery("customer.updateSentToBusinessCheckByCustomerIds").setParameter("customerIds",customerIds);
        int size=customerIds.size();
        if(size>30000){
            List<Long> customerIdsSplit=new ArrayList<Long>();
            for(int i=0;i<size;i++){
                customerIdsSplit.add(customerIds.get(i));
                if(customerIdsSplit.size()==30000){
                    updateList(customerIdsSplit);
                    customerIdsSplit.clear();
                }
            }
            updateList(customerIdsSplit);
        }else{
            updateList(customerIds);
        }
    ......    

    private void updateList(List<Long> customerIdsSplit) {
        Query query = emMain.createNamedQuery("customer.updateSentToBusinessCheckByCustomerIds")
                     .setParameter("customerIds",customerIdsSplit);
        query.executeUpdate();
    }

关于解决问题的东西到此结束了,但是以上都不是本文的重点,有几点感触比较深刻的。

1. 篇博客自己很喜欢,代码很少重在思路。

2. 看源码,是90%问题的解决之道,前提是时间允许。

3. 一切有因有果(这里指那三万多这个数字是有他的来头的)。

后记

都说程序员,或者软件行业是是需要高智商的,我不这么认为,论据如下:解决完这个问题之后想起来每天都能听到公交车司机咆哮的那句话,“上不去的乘客等下一辆吧!后面跟着一辆呢!!后面的那辆马上就到了!!!”这不就是人太多坐不下然后就需要分批运送么,和上面的问题解决思路是一样的啊!如此可见公交车司机和程序员(或者说工程师)的职位对智商要求是一样的。最后的最后,附图一张聊表心意。

(在车上拍的,当时算了一下,不禁心中一惊)

上一篇:上一篇
下一篇:下一篇

 

随机推荐程序问答结果

 

 

如对文章有任何疑问请提交到问题反馈,或者您对内容不满意,请您反馈给我们DOC100.NET论坛发贴求解。
DOC100.NET资源网,机器学习分类整理更新日期::2014-01-05 02:06:58
如需转载,请注明文章出处和来源网址:http://www.doc100.net/bugs/t/5778/
本文WWW.DOC100.NET DOC100.NET版权所有。