C3p0 的一个异常

转的,异常如下:

NewPooledConnection - [email protected] closed by a client.
java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:566)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:234)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.destroyRe
source(C3P0PooledConnectionPool.java:470)
at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.java:96
4)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.ja
va:547)
C3P0PooledConnectionPool - Successfully destroyed PooledConnection: com.mchange.v2.c3p0.impl.NewPool
[email protected]

我看到那个DEBUG,我说,是调试信息,修改一下LOG4J的等级就行了。

这个群友很不解的问,既然成功了,干嘛还要丢异常出来?

这里就不得不说到两个商业开发的原则问题了。

第一,对上家传入数据严加过滤,对传出给下家的数据仔细检查。

第二,合理使用异常。

第一点其实很简单的。也就是模块化开发的一个思想问题。对自己的行为负责。前端返回的数据究竟是什么,需要进行校验。不合格的剔除或者是修正。合格的处理完后,在传出之前也要加以校验,是否合格。

具体到这个问题里,就是来自Spring关于数据源的那个配置文件。

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

//略去数据源相关信息的配置

</bean>

这个配置文件里,有两个信息是很管用的。一个是class,一个是destroy-method。简单点说,一个是数据源的实现类,一个是析构方 法。Spring在读取这个配置文件以后,需要根据这些信息来实例化一些类,然后内部再根据中间的那些配置信息来实际构造数据源。比如username啥 的。

可是来了个问题。不能保证这里的ComboPooledDataSource数据源一定是可用的,也不能保证close方法一定能关闭连接,对 吧?Spring本身不能检查这个类是否真实有效,毫无Bug。实际上呢,也检查不了。同样的,close方法是否有效,也需要进行检查。这就是我刚才说 的,对上家数据的严加检查。

那好吧,怎么检查呢?最简洁的方法莫过于实际构造一下,连接池,获取数据库连接,执行一个测试语句,然后关闭连接。如果一切都成功,那就OK。关于 那个测试语句,配置过WebSphere数据源的同学们还记得不?有个SQL语句会默认的写在数据源配置里,是 " SELECT 1 FROM TABLE "。嗯,对的,这个就是测试语句。

这一套流程能走得通,走的顺,那么就可以在自己能力范围内说这个数据源和连接池是能用的,对吧?

这里补充一个知识。java.sql.Connection,这玩意不是class,是interface。

声明是:public interface Connection extends Wrapper 。

任何一个JDBC数据库连接的实现类都应该实现这个接口的全部方法。比如,close。API里的描述是,立即释放此Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。

熟悉Java的同学们应该记得一点,在规范里有个要求,就是接口的实现类必须实现接口的所有方法。但是呢,这句话还有个意思,那就是,你可以在实现所有方法之外,再写几个方法。没人会管你。

啊哈,那就有疑问了。虽然API规定了close是关闭连接释放资源的。但这只是你接口的一厢情愿。也许人家实现厂家觉得close方法不够帅,要 改成closeConnection。那。。。Spring总不好傻傻的去死扣close方法来关闭连接吧?虽然这方法必须实现,但是可没说一定要有内容 啊。如果是空方法呢?

所以有了destroy-method这个配置项的出现。Spring说,不碍的,您老人家看哪个爽,告诉我就行。

现在测试完了。一切都成功了。

现在来看看第二个问题。合理使用异常。

又遇到一个问题。既然测试成功了,那总得给用户一点交待吧?难道说,测试成功了,就闷声大发财了?显然不合适嘛。可以试想一下,你是程序员,然后点 了个按钮,测试。结果呢,实际上是测试成功了,但是系统啥动静都不给你。然后你傻傻的等痴痴的盼,一直等到天荒地老……嗯嗯,扯的有点远。如果你等一个小 时还不见动静,活不见人死不见尸的,你说你会不会骂娘?

那么怎么通知才能保证一定有效呢?println?这个不见得一定能看到。因为别人也可能在同时输出信息,一下就刷掉了。那么有同学说了,最好是能暂停一下,我输出以后,就暂停了,不动了。

嗯,很好。

大家想想看,输出一大堆东西,然后此程序不动了,不继续执行了,这是啥玩意?

这不就是异常嘛!

只有异常能保证程序员一定能看到这个信息,比如,测试成功。这就是为什么Spring要采用这种方式来通知的原因。

这里呢,我想更正同学们一个习惯成自然的想法。异常不一定是通知坏消息的。异常就是异常,只要你愿意,你甚至可以在代码执行成功的时候,throws一个Exception。异常只不过是比较激烈的一种通知方式而已。无他,仅此而已。

现在又有个问题来了。既然要测试,而且每次执行到此处的时候都要测试一下。那么……难道都卡在这里不走了啊?显然更不合适啊。

熟悉log4J的同学应该看出来了,这是log4J输出的日 志。很明显的,这种日志只应当在开发期间存在,不应该在发布期间存在。因为开发期间数据库变动很大,比如改表啊,改数据库配置啊。所以需要通知用户是否成 功。但是产品一旦开发完毕,正式发布,这种信息就不应再出现,因为商业化运作的应用不允许乱动配置的,对不?

所以log4J提供了一种方法。消息级别。INFO的时候,是看不到这个异常的。实现起来也很好办,catch了,然后不做任何处理,也就是空的catch块。

具体实现的时候可以在catch里判断一下,如果等级是INFO的话,就不做任何事。如果不是,那就按照规则去做。

结合到 “合理使用异常” 这句话来说呢,就是说,需要抛出异常的时候,就抛出。不需要抛出的时候,就不抛出。对程序员来说,在必要的时候看到一串异常信息,是最合适的事情了。

时间: 2024-08-08 22:08:08

C3p0 的一个异常的相关文章

一个异常的排除

今天用Basemap库构建地图时出现了一个异常,谷歌了无数次,却还是没有解决,想到时间就要花在这该死的异常上,纠结万分.最后快要放弃时,我调整了几个库的import顺序,将gdal放在最后,异常奇迹般没了.心中有多少槽也吐不尽啊,昨天看电影十万个冷笑话,吐槽可以转化为能量,那我该有多少能量啊. pycharm上显示:“Assertion failed: (0), function query, file AbstractSTRtree.cpp, line 286.”并且弹出框“使用libgeos

VS开发ArcEngine时的一个异常信息——“ArcGIS version not specified. You must call RuntimeManager.Bind before creating any ArcGIS components.”

问题描述:程序报错"ArcGIS version not specified. You must call RuntimeManager.Bind before creating any ArcGIS components." 解决方法:打开program.cs. 把ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop); 放到Application.SetCompatibleTextRender

在ASP.NET MVC中使用NuGet添加SignalR类库之后,再次运行程序时,它出现了一个异常:

自从在ASP.NET MVC中使用NuGet添加SignalR类库之后,再次运行程序时,它出现了一个异常: Server Error in '/' Application. The following errors occurred while attempting to load the app.- No assembly found containing an OwinStartupAttribute.- No assembly found containing a Startup or [

如何自定义一个异常类

如何自己定义一个异常类来管理相应的异常? 1) 为这个找一个近似的类作为父类. 2) 在该类中编写两个构造器: a) 默认构造器; b) 带String message参数的构造器且在该构造器中使用 super(message); 语句     来调用父类的构造器完成异常原因的更改. 以下实例为,创建一个小猫对象,其年龄为负数则显示为异常 public class Exception7 { public static void main(String[] args) { Cat c1=null;

如何开发一个异常检测系统:如何评价一个异常检测算法

利用数值来评价一个异常检测算法的重要性 使用实数评价法很重要,当你用某个算法来开发一个具体的机器学习应用时,你常常需要做出很多决定,如选择什么样的特征等等,如果你能找到如何来评价算法,直接返回一个实数来告诉你算法的好坏,那样你做决定就会更容易一些.如现在有一个特征,要不要将这个特征考虑进来?如果你带上这个特征运行你的算法,再去掉这个特征运行你的算法,得到返回的实数,这个实数直接告诉你加上这个特征算法是变好了还是变坏了,这样你就有一种更简单的算法来确定是否要加上这个特征. 为了更快地开发出一个异常

【ThinkingInJava】24、捕获一个异常之后抛出另外一个异常,并且希望吧原始的信息保存下来

/** * 书本:<Thinking In Java> * 功能:捕获一个异常之后抛出另外一个异常,并且希望吧原始的信息保存下来,这个被称为异常链 * 文件:DynamicFields.java * 时间:2015年4月9日16:24:44 * 作者:cutter_point */ package Lesson12_error_handling_with_exceptions; import static net.mindview.util.Print.*; class DynamicFiel

More Effective C++----(12)理解&quot;抛出一个异常&quot;与&quot;传递一个参数&quot;或&quot;调用一个虚函数&quot;间的差异

Item M12:理解"抛出一个异常"与"传递一个参数"或"调用一个虚函数"间的差异 从语法上看,在函数里声明参数与在catch子句中声明参数几乎没有什么差别: class Widget { ... }; //一个类,具体是什么类 // 在这里并不重要 void f1(Widget w); // 一些函数,其参数分别为 void f2(Widget& w); // Widget, Widget&,或 void f3(const W

从一个异常探索spring autowired 的原理

从一个异常探索autowired 的原理. 首先环境是这样的: public class Boss { @Autowired private Car car; } //@Component 加上这个注释,上面的Boss 的Autowired car就会失败,出现下面的异常 public class Car { private String brand; private double price; } xml 是这样的: <?xml version="1.0" encoding=&

怎样自定义一个异常(报错) 并抛出

1. 自定义一个异常需要使用构造函数 Error() var error1 = new Error("This is an unknown error."); 2. 抛出异常需要使用 throw 关键字 var error1 = new Error("This is an unknown error."); throw error1; 执行后就可以得到这样的效果: 原文地址:https://www.cnblogs.com/aisowe/p/11655006.html