| 云 的个人资料小木屋照片日志列表 | 帮助 |
|
|
Eclipse快捷键大全Ctrl+Shift+L 列出所有快捷键的快捷键,哇哈哈 推荐《Dreaming in Code/梦断代码》
此书基本上不属于技术类书籍,但我觉得应是程序员所乐于见到的故事和文字。严重推荐给曾经是程序员或者仍是程序员的同学们。 附: 本书英文版网站:http://www.dreamingincode.com/ 中文版网站:http://www.dreamingincode.cn/ 书中主角Chandler项目网站:http://chandlerproject.org/ 关于注册Weblogic9为Windows服务的一些细节首先,找到的这篇blog的方法是work的,致谢。 原文如下: Weblogic8时代将weblogic注册成为Windows服务是一件很简单的事,只要执行Domain目录下的 installService.cmd即可。不过进入Weblogic9之后,domain目录下就没有了那个脚本,而是出现在%WL_HOME%/server/bin下,直接运行会生成一个“bea _”的服务,运行的话。。。没有任何结果,BEA的edocs上也没有找到有用的帮助。 以下内容,是我盯着installService.cmd和startWeblogic.cmd出神良久后试验成功的。
beasvc命令各个参数的详细意义可以参考beasvc /help 以上内容对于Oracle Weblogic 10依旧有效。
这里面有个问题,就是如果之前改过startWebLogic.cmd的参数,例如MEM_ARGS,file.encoding等等就不生效了,因为注册服务的脚本并不是通过startWebLogic.cmd启动的。所以你的参数需要在installSvc.cmd脚本中重新设定(最终体现在CMDLINE)。特别注意此脚本中的跳转(goto)语句,确保你自己的语句会被执行到。 可以到注册表 H_L_M/SYSTEM/CurrentControlSet/Services/你的服务名 下查看服务是否正常。CMDLINE在Parameters下。直接修改这里再重启,也可以生效。 猜想:磁盘分区边界对齐对虚拟机io性能的影响昨天做了个VM,直接在装Windows的时候分的区,结果在操作涉及大量文件读写的时候(例如:在eclipse中对svn repository relocate,需要更改所有.svn目录下的Entries文件;10个线程的ftp下载;search文件数量非常多的目录等)就会停顿,假死。 怀疑是虚拟机磁盘io的问题,重新做了一个VM,在安装系统前,winpe启动,用diskpart分区,在create partition的时候加上align=64的参数,让分区边界对齐。再装系统之后似乎停顿的现象少了很多。 使用HD Tune做了一下简单测试,做了对齐的VM磁盘性能明显优于第一台。特别是在随机读写数据大小为512k时,有5倍以上的差别。 如果你是虚拟机管理员,最好是做一个优化好的无敌模板,省力又省心。 网上这篇文章说得好像算明白了,看上去像是翻译的(就不能翻译得好点吗?!)。 http://jackiechen.blog.51cto.com/196075/163284
以上为无责任评测。 hibernate使用Weblogic datasource的事务问题在hibernate中配置使用weblogic datasource比较简单,在hibernate.cfg.xml文件中将直接jdbc连接的配置: <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> 替换成: <property name="connection.datasource">myDatasource</property> 即可。 如果有需要,也可以加上connection.username,connection.password两个配置。 但是如果事务配置沿用之前的: <property name="current_session_context_class">thread</property> 而weblogic中配置的datasource又是默认设置的话,就会报事务的错。错误信息如下: java.sql.SQLException: Cannot call Connection.commit in distributed transaction. Transaction Manager will commit the resource manager when the distributed transaction is committed. 大概的意思是无法在一个分布式的事务中提交。个人猜想,问题应该是出在hibernate和weblogic都有自己的事务管理,所以就变成distributed transaction了。 解决的办法有两个: 1.配置weblogic datasource时,将Honor Global Transactions option这个选项uncheck。(注意此选项只能在新建数据源的时候配置,如果你已经有一个数据源,只能删除重建了)。 2.不修改数据源,使用jta,并且将jta的事务管理配置成weblogic的。具体方法是在hibernate.cfg.xml中删除原来thread的配置,然后增加这几行: <property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property> 个人觉得第二种方法比较好,原因:(1)weblogic在Honor Global Transactions option的说明里提出,uncheck这个选项非常少见而且有风险;(2)你不一定有权限修改datasource的配置。 ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值最近项目中需要在一个表的字段中插入长的字符串,数据表中该字段的类型是varchar2(4000),结果发现,当字符串长度在1000~2000之间的时候,就会报错,而当字符串长度在1000以下或者2001~4000的时候都没问题,显然这是Oracle的一个bug。错误信息如下: 15:59:46,953 ERROR [JDBCExceptionReporter] Could not execute JDBC batch update at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343) 如果把insert或者update语句直接在PL/SQL里面跑,或者拼成sql语句在程序里执行,都是没问题的,但是如果是用ojdbc驱动的方法(包括hibernate),就会出错。此外,在另外一台Linux的机器上的Oracle9.2.0.8就没问题(生产机是Windows系统,Oracle9.2.0.1)。 经过google和多个交叉测试,排除了操作系统、中间件平台(Weblogic)的问题。在红伟的指点下,找到这么一个网页,把这个问题的原因说得好像比较清楚(wordpress的,需要翻墙):http://vsadilovskiy.wordpress.com/2007/10/19/ora-01461-can-bind-a-long-value-only-for-insert-into-a-long-column/ 里面提到的解决办法是,用新版的ojdbc驱动,然后把OracleDatasource的oracle.jdbc.RetainV9LongBindBehavior属性设为true,经测试,并不生效。测试了从Oracle网站下载的不同版本(9i,10g各小版本)的ojdbc.jar,情况依旧。 最后,把生产机的Oracle升级到9.2.0.8,问题解决。 ------------------------------------------------------------ 附:上面提到的网页的文字拷贝 ORA-01461: can bind a LONG value only for insert into a LONG column October 19, 2007 — Vlad Sadilovskiy Just one another issue with JDBC I think is worth mentioning. You perhaps wonder why so obvious error message could be troublesome to comprehend. Unfortunately, it speaks of things that a developer never meant to happen. It doesn’t have to be a LONG value. This error could appear when ASCII strings are bound for VARCHAR2 columns. In this case it happens when JDBC v. 10.1/2 is used with a Oracle Server 9i database configured for multi-byte character set. Before going any further, please note that according to support matrix Oracle JDBC 10g and 9i are cross supported with Oracle Server 9i and 10g. For the testing I used two databases Oracle 10g and Oracle 9i with database character set UTF8 and JDBC 10.2.0.3. Some of the Asian language characters can consume up to 3 bytes in UTF8 encoding. But can you expect that a string composed of 1334 ASCII characters would not bind for VARCHAR2(4000)? However, it is possible. Let’s dig up little more details. Here is how the string of 4000 “a” characters would appear to the Oracle 9iwhen bound from JDBC 10g with default properties. This bind is not spooled into the 10046 trace file. Instead it can be captured by enabling stacktrace dump on 1461 event. bind 19: dty=1 mxl=4001(12000) mal=00 scl=00 pre=00 oacflg=03 oacfl2=10 size=4000 offset=0 Oracle Server 10g. Note, that when you test this scenario, there are no errors – Oracle Server 10g is perfectly fine with the 12000 bytes in the private buffer. Bind#19 According to Metalink Note: 3756847.8 this problem was introduced in some 10.1 versions of JDBC, but was fixed in 10.2. However, it is not enabled by default. Following JDBC connection property enables the fix. java.util.Properties props = new java.util.Properties(); And here is how the bind looks like after the fix is enabled. Oracle Server 9i: bind 19: dty=1 mxl=4000(4000) mal=00 scl=00 pre=00 oacflg=03 oacfl2=10 size=4000 offset=0 Oracle Server 10g: Bind#19 There is no need in enabling this fix for 10g/10g setup. 10g version of the trace is shown just for comparison purposes. In conclusion I want to clarify that this article describes the unexpected behavior with legitimate length values. However, there are other cases when apparently correct values fail to insert with same message. I.e. already mentioned strings that, when using UTF8 for database character set, can expand from 4000 Asian language characters to up to 12000 byte values. In these cases, Notes: 241358.1, 370438.1 recommend different workarounds. Note: 445072.1 has decent example of getting the length of encoded string and suggests converting VARCHAR2 columns into CLOB if encoded string length exceeds maximum length of VARCHAR2 type. WebLogic不同版本之间JMS发送问题,及在EJB里使用Spring根据查得的资料以及试验的结果,用weblogic9.2或者8.1的wlclient.jar,wljmsclient.jar或者weblogic.jar,写客户端程序向weblogic7.0发送JMS都会有问题,EJB调用则正常。一般的建议方法是将weblogic7.0的weblogic.jar引入。但在我的项目里,7.0的weblogic.jar的xml解析器和加载Spring时用的xml解析器冲突,而且将来的app是部署到9.2上的,用7.0的weblogic.jar,谁也不敢担保部署之后会发生什么事。再说了,一个客户端程序包含服务器端的jar包,也太不优雅了。 所以决定还是用weblogic9.2的wlclient.jar,wljmsclient.jar,解决方法也很简单(但也花了我小半天的时间摸索呢),在weblogic9.2 server上多建一个JMS Queue,然后再配一个JMS Bridge将这个Queue和7.0 server上的JMS Queue连接起来,算是比较好的解决了这个问题。 我们都知道,在web application里面使用Spring,只需要简单地在web.xml里面添加配置文件及Spring Listener的信息即可,那在EJB中要使用Spring又怎么弄呢....反正我只知道显式加载Spring的application-Context.xml配置文件了。在bean里增加一个相应的变量即可。例如一个MDB: package com.mdb.ejb; import javax.ejb.EJBException; public class myMDB implements MessageDrivenBean, MessageListener { /** *//** The MessageDrivenContext */ public myMDB() { public void setMessageDrivenContext(MessageDrivenContext newContext) public void onMessage(Message recvMsg) { System.out.println(message.getText()); public void ejbCreate() { public void ejbRemove() throws EJBException { } //别忘了把application-context.xml放到class path下,在EJB里,放jar包的根目录就行了。 上面的程序主要来自http://blog.csdn.net/myid/archive/2006/09/20/1253789.aspx,鸣谢。 本阶段的探索基本上告一段落,真是知道得越多,越觉得自己知道得越少啊。 Free Software We're Most Thankful Forfrom: http://lifehacker.com/5098944/free-software-were-most-thankful-for
黑色为用过或者正在用,Firefox自不必说,Launchy也是不错的软件。Google的各种applications当然必不可少了。 另外推荐两个小工具:AutoRuns和Process Explorer。在病毒木马恶意软件横行的年代,怎么能少了这两个软件呢? Spring+weblogic 焦头烂额开始时将MDB deploy到weblogic9.2的时候就不熟练,admin console界面比8.1变化不小,配JMS的时候更加是问题多多,JMS Server、JMS Module、JMS resource,subdeployment,真是一头烟。网上的教程语焉不详,还有不知道是不是故意为之的拼写错误,不可尽信。 备忘: 1. 在同一个JMS Module中创建不同的subdeployment,然后ConnectionFactory和Queue要配给不同的subdeployment,ConnectionFactory target到你的server,Queue target到JMS Server。 2. 可以在server->view JNDI tree那里看你的ConnectionFactory和Queue配置成功了没有。如果它们对应的JNDI Name在tree里面出现了,那恭喜你,可以写程序来测试了。 3. 因为EJB是容器加载的,所以要用到的jar包,除了放在weblogic server的class path(在启动脚本里面加)里的方法外,据说还可以在META-INF/manifest.mf文件中用类似Class-Path:log4j.jar的方式引入,但貌似这个依赖包(如log4j.jar)的路径要从ejb的jar包所在目录算起,复杂而且不优雅。 如果是Enterprise Application(.ear)或Web Application(.war),那就简单多了,把需要用到的jar包放到APP-INF/lib或WEB-INF/lib下面就行了,非JEE标准,但weblogic支持,几乎已经是默认标准了。 EJB自己用的配置文件,例如log4j.properties,直接放在它自己的Classe Loader目录一起打包即可。
发布Web Application的时候继续麻烦不断。不知道谁手多多在application-context.xml文件里面加了一个log4j相关的Listener和log4j.properties路径配置。但war包是容器加载的,那个路径根本不在Class Loader所能到达的地方,只有在Spring加载之后才有可能到达,但Spring加载过程中所读的配置文件中需要找到这个文件,这鸡啊蛋蛋啊鸡,你等我我等你,最终只能fail了。 所以啊,别在war包里面使用与Class Loader路径以外相关的咚咚,weblogic只会给你返回一个null。把log4j.properties文件乖乖地放到class loader目录下算了。 然后还遇到一个问题,当weblogic.xml的<prefer-web-inf-classes>参数值为true的时候,很容易造成java.lang.ClassCastException。bea的支持文档里面是这么说的: The weblogic.xml Web application deployment descriptor contains a prefer-web-inf-classes element (a sub-element of the container-descriptor element). By default, this element is set to False. Setting this element to True subverts the classloader delegation model so that class definitions from the Web application are loaded in preference to class definitions in higher-level classloaders. This allows a Web application to use its own version of a third-party class, which might also be part of WebLogic Server. See "weblogic.xml Deployment Descriptor Elements." When using this feature, you must be careful not to mix instances created from the Web application's class definition with issuances created from the server's definition. If such instances are mixed, a ClassCastException results. 我猜我们是有个xml转换类跟weblogic自己的mix了。一个类似的问题描述:http://www.javaeye.com/topic/255848
接下来就是把连接参数提取出来放到配置文件,用注入的方式供程序使用,实现Spring+EJB、Spring+JMS,网上例子很多,不详述了。突然想,如果bean里面的用到property的value可以映射到hibernate.xml里面的某表某字段,然后自动通过key取到数据库里的值,但基本上系统参数不都可以放到数据库里,然后自动注入了?what a wonderful spring!可惜google了一大轮,没找到类似应用的描述,作罢。似乎还是需要写一个相应的POJO来映射?hmmm,有空再想想。
weblogic9.2的EJB、JMS远程访问权限在哪配啊啊啊啊,为什么匿名可以访问,有用户/密码反而不行,要疯了.... 定时关机的方法运行,cmd,进入命令行模式。 at xx:xx shutdown -s -f -f参数是指强行关闭应用程序,因为有些程序会死不断气的,建议加这个参数。 前提:task schedule(计划任务)服务是开着的,可留意看命令执行之后的提示。 取消: shutdown -a 遭遇业务人员经典语录这几天在写一个系统的需求,遭遇了不少教科书式的业务人员语录,随手记录一下。 “流程很简单啊,没什么可说的。” “你都很清楚啦,我只管到时候测试和使用就行了。” “原来的系统有这个功能?没用过……” “在老系统那个功能基础上改一下就行啦。” “我们这个和他们那个是一样的,照他们的做就行了。” “我需要的只是一个报表,所有我要的数据都有。(前面的步骤我不管)” “这个实现起来很容易吧。” “这两个报表要保存到数据库两个不同的表里面。” 以下省略。 修复损坏的WMI(Windows Management Instrumentation)服务今天准备共享网络给同事上网的时候,发现网络设置-高级那里的共享选项看不到了,取而代之的是WMI服务信息损坏,需要使用系统还原功能修复的提示。见鬼的系统还原,估计没几个人还开着这个服务的吧。到计算机管理-服务里面一看,Windows Management Instrumentation服务居然不见了,晕。 于是借助万能的google,果然…… 原文地址如下:http://blog.romman.net/120/viewspace-3138.html 方法是用脚本重新将WMI修复一下,脚本内容如下:
@echo on
将以上内容放到文本文件中,另存为一个.bat文件(文件名任意),然后运行,问题就解决了。这牛人还是多啊…… oracle的数据导出导入——exp/imp前几天拿到一个系统的升级包,需要导入数据,数据文件是用oracle的exp工具导出的*.dmp文件。 自然是用imp命令导入了。exp/imp在安装了oracle客户端之后,在%Oracle_home%/bin下面就有了。详细信息可以用以下命令看: >exp help=y >imp help=y 不过有个问题是,用DBA导出的数据,必须有DBA权限才能导入。哪怕imp的时候指定fromuser和touser参数也不行,而我手上只有测试用户,自然不是DBA了,郁闷。最后还是要找数据库管理员临时给了测试用户DBA权限才行。 用exp导出的数据文件,可以用quest的Toad for Oracle工具查看具体内容,以及导出相应的SQL语句。不过话说回来,如果不是有clob类型的字段,一般也不会用exp/imp方式来导出导入数据了,因为直接用pl/sql导出sql语句还是最方便的,除非数据量极大。 当然,exp/imp还有一个作用就是备份/恢复数据库,那就另说了。此外,exp/imp还有一些细小的问题要注意,例如不同用户的表空间等等。最后一点,如果可以,最好是先把需要导数的表备份,然后drop掉再imp数据,否则导入的结果未必如你所愿。 ClearCase check in之后文件名大写变小写?teamate在虚拟机上——为什么要用虚拟机,因为破ClearCase要用域认证,而大家都不愿意把自己的机器加入域——在虚拟机上check in文件之后,发现所有文件名都变成小写了,于是update出来之后所有java类都编译不通过——因为对于case sensitive的Java编译器来说,类名和文件名不一致。但check in之前在Explorer里面看到的文件名大小写都是正确的。 查了一下,说是在控制面板的ClearCase配置页MVFS里,有个选项可以设置Case Insensitive和Case Preserving参数,但这个是动态视图才有的,而我们建的都是静态视图。 更怪异的是,我们的机器上所有操作都正常,难道这是虚拟机的问题? Eclipse里面的java编译选项project -> preference -> Java Compiler 这里Enable project specific settings之后,可以设置不同版本JDK兼容性的参数,例如那个烦人的"enum should not be used as an identifier,since it is a reserved keyword from source level 5.0 on",在JDK5.0里面,enum是个关键字,所以一般选用JDK1.4的时候,默认就会有warning。最好的办法当然是rename所有叫enum的identifier,以免JDK换到5.0的时候编译无法通过。 但如果这是别人的代码,你不能改,但又不想在编译的时候看到这么多的warning的话(太多同一类的warning排在前面,后面的就看不到了),就可以将Disallow identifier called 'enum'这一项的编译级别从Warning改成Ignore。
在Java Compiler的子项里,可以对各种Errors/Warnings进行设置。在开发阶段,我觉得将Assignment has no effect(e.g.'x=x'),Possible accidental boolean assignment(e.g. if (a=b))等等设为Error比较好,因为通常这些代码只有写错的时候才会出现,而且很可能会影响你的程序的逻辑。此外,相对严格的编译选项有助于keep your code clean, and simple。
如果想对所有workspace里面的project都使用同一配置,可以点右上角的Configure Workspace Settings....的链接。 网页中如何建可以点击展开和合拢的目录原来非常简单,just like this. <div id="main1" style="color:blue" onclick="document.all.child1.style.display=(document.all.child1.style.display =='none')?'':'none'" > 可嵌套。 其中<span>那个tag是定义鼠标指针用的,因为指着目录标题的时候还是文本鼠标指针看着很不习惯,IE6和firefox的cursor:pointer就是那只手了。 oracle数据类型的隐性转换今天,以前开发的一个系统出问题,一句类似这样的sql语句: select * from t where a=1 其中a是varchar类型。在测试机上跑得好好的,在生产机就报invalid number的错。原因涉及oracle数据库在解析sql语句的时候,对数据进行了类型转换,实际执行的是: select * from t where to_number(a)=1 只要表t里面有一条记录的a字段含有不能转换为number的数字,就出错了,而错误当然就是invalid number了。 此外,由于这样写语句要对表中a字段所有数据都做一次运算,什么索引都没用了,每次搜索都会进行全表扫描和运算,造成性能的下降。所以,就算不出错,也一定要根据数据类型写sql语句。如上例,写成这样就好了: select * from t where a='1' 当然,因为这个系统比较小,业务简单,所以是用简单jsp实现的,所有sql语句都自己生成。如果大一点的系统,就可能会用到框架。如何优化对数据库的访问很大程度上都是框架的问题了。 下面是网上搜索到的一篇关于oracle数据类型隐性转换的文章: ORACLE数据类型的隐性转换 出于优化的目的,在SQL 的编码中我们常提到要避免对字段进行计算,通常情况下字段的计算导致相应索引无法被使用,造成语句执行的开销增大,然而编码中稍有不慎,Oracle自动进行的隐性转换仍有可能进行了我们不希望看到的操作,进而带来严重的后果,索引扫描可能被替换为几千万行的全表扫描,甚至导致业务逻辑发生变化。因此本文列举了代码中常见的几种隐性类型转换,总结并论证其间的规律,以期在开发工作中避免其带来的危害。 为举例创建一个表,包含隐性转换中常见的三种字段类型,并给每个字段建一个索引: ********************************************************* create table TT2 ( NUMCOL NUMBER, CHARCOL CHAR(10), VARCHARCOL VARCHAR2(10) ); create index IDX_CHAR on TT2 (CHARCOL); create index IDX_NUM on TT2 (NUMCOL); create index IDX_VARCHAR on TT2 (VARCHARCOL); insert into tt2 (numcol,charcol,varcharcol) values (1,'123','1'); ********************************************************* 首先将varchar字段与number常量进行比较。 ********************************************************* SQL> select /*+ RULE*/ * from tt2 where varcharcol=1; NUMCOL CHARCOL VARCHARCOL ---------- ---------- ---------- 1 123 1 Execution Plan --------------------------------------------------------- 0 SELECT STATEMENT Optimizer=HINT: RULE 1 0 TABLE ACCESS (FULL) OF 'TT2' ********************************************************* 这里我们加入了一个RULE 的提示,指定了RBO的优化方式,因此有索引的情况下理所当然优先使用索引,但是恰恰相反,执行计划选择了全表扫描,究其原因,乃是隐性地对 varchar2类型的字段进行了to_number的转换从而屏蔽了索引,实际的Where条件为to_number(varcharcol)=1 变换一下,用number字段与字符常量比较。 ********************************************************* SQL> select /*+ RULE */ * from tt2 where numcol='1'; NUMCOL CHARCOL VARCHARCOL ---------- ---------- ---------- 1 123 1 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=HINT: RULE 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TT2' 2 1 INDEX (RANGE SCAN) OF 'IDX_NUM' (NON-UNIQUE) ********************************************************* 执行计划使用了IDX_NUM索引,这次隐性转换没有去转换number字段,而是转换常量'1',实际的where条件变化为where numcol=to_number('1'),字段避免了计算,索引得以被使用。 由此可见,字符与数字相遇时数字类型要厉害一些,Oracle总要偷偷将字符类型进行转换去迁就数字,为了论证这个结论,接上例,再做如下测试。 ********************************************************* SQL> select * from tt2 where varcharcol=1; NUMCOL CHARCOL VARCHARCOL ---------- ---------- ---------- 1 123 1 SQL> update tt2 set varcharcol='1A'; 1 row updated. SQL> select * from tt2 where varcharcol=1; ERROR at line 1: ORA-01722: invalid number ********************************************************* 同样的语句前者执行成功,后者却执行失败,什么都没有变,只是varcharcol字段的值由'1'变成'1A',隐性转换做to_number(varcharcol)操作时,后者无法将字母转换成数字导致ORA-01722错误发生,由此可见这种转换是确实存在的。 接下来,再看看关于Char类型的转换,还有值得我们注意的事情发生。 首先将char类型字段与varchar2进行比较,上例中charcol为char(10)类型,由于char类型的特性,插入的值'123'被自动补齐空格至10位长,因此字段值其实为'123 ',我们执行如下匿名块,并使用SQL_Trace提取执行计划。 ********************************************************* declare vv varchar2(10):='123'; begin UPDATE /*+ RULE*/ tt2 set numcol=1 where charcol=vv; end; / Rows Row Source Operation ------- --------------------------------------------------- 0 UPDATE 0 INDEX RANGE SCAN IDX_CHAR (object id 28748) ********************************************************* Rows为0,说明没有行被更新,'123 '与'123'理应为不同的值,这样的结果合理,然而在RBO方式下IDX_CHAR索引被使用,可见并没有对charcol进行隐性的转换。 可是,将char类型字段与字符串常量进行比较呢? ********************************************************* SQL> select /*+ RULE */ * from tt2 where charcol='123'; NUMCOL CHARCOL VARCHARCOL ---------- ---------- ---------- 1 123 1A Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=HINT: RULE 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TT2' 2 1 INDEX (RANGE SCAN) OF 'IDX_CHAR' (NON-UNIQUE) ********************************************************* 居然有数据返回,并且IDX_CHAR 索引被使用,岂不是'123 '与'123'相等,同样的where语句,同样是字符串'123',因为隐性转换产生了不同的逻辑,原来char与字符串常量比较时,隐性将常量按 char的字段类型转换,'123'转换成char(10)则变成了'123 ',看来使用char类型得小心了,两种不同的结果其实就对应着我们在应用开发中将SQL放在存储过程中还是放在中间件或前台代码中。 做了这么多例证,掌握了常用的转换规律后,我们在数据库开发中应该注意些什么呢: 1、 表结构设计中字段的类型以及数据库代码变量的类型应慎用char类型,采用这种类型的数据必须满足两个条件:1)非空;2)有固定长度。 2、 规范编码,尽量避免隐性转换,比较中使用相同类型。 在代码中构造动态SQL时,对字符串类型字段的比较中常有这种情况发生,实际上构造的语句是将字符与数字进行比较。 v_SQL:=' ... where varcharcol='||v_str; 正确的做法应该是 v_SQL:=' ... where varcharcol='''||v_str||''''; 3、 某些标记性或开关意义的字段,取值范围诸如(0,1),(1、2、3)等,尽量使用NUMBER,而不要使用varchar2。 如果where varcharcol='1'误写为 where varcharcol=1将可能造成严重的性能问题,频繁隐性类型转换还可能造成不可预期的ORA-06512 错误,而 where numcol=1 误写为 where numcol='1'则没有太多不利影响。 越界访问?2呵呵,问题解决了。首先,build clean之后(这不也是3-re调试大法——rebuild、restart、reboot之一么,周五怎么就没想起来,看来技艺生疏了),debug也会进入报错抛exception的流程了。然后发现出错的原因是数据库表忘了设主键,框架的数据库访问组件在update记录的时候找不到表的主键,拼SQL语句的时候where后面的条件就出不来,于是就出错了。 看来,万事皆有因。 越界访问?周五调试的时候遇到一个诡异的问题,debug的时候可以正常走完,run的时候就报错。晕,这不是C/C++时代越界访问时出现的问题吗,怎么Java也好这一口。 调试用的服务器是Eclipse起的Weblogic8.1 Server,系统读写数据库这块又用了开发公司的JFrame框架,不知道问题出在哪里了,头大。又难道,是因为半个月没重启PC导致的? 周五出个这样的问题,很不爽,现在进度超前这么多,总不能周末回去加班吧.... |
|
|