posts - 31,  comments - 31,  trackbacks - 0
       这几天做项目,需要做一个类似于控制台的界面,可以将日志回显到一个文本区域里,几经查找,反复测试写了以下测试代码。
这是log4j.properties的配置内容
    log4j.rootCategory= ,WriterAppender

log4j.appender.WriterAppender
=org.apache.log4j.WriterAppender
log4j.appender.WriterAppender.Threshold
=debug
log4j.appender.WriterAppender.layout
=org.apache.log4j.PatternLayout
log4j.appender.WriterAppender.layout.ConversionPattern
=%d{ISO8601} - %- %m%n
主程序
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Writer;

import org.apache.log4j.Appender;
import org.apache.log4j.Logger;
import org.apache.log4j.WriterAppender;

public class Log4jMain {
    
static public Logger logger = Logger.getLogger(Log4jMain.class);

    
public static void main(String[] arg) {
        
        
        Logger root 
= Logger.getRootLogger();
        
try {
            Appender appender 
= root.getAppender("WriterAppender");
            PipedReader reader 
= new PipedReader();
            Writer writer 
= new PipedWriter( reader) ;
        
            ((WriterAppender) appender).setWriter(writer);
            
            Thread t 
= new AaaThread(reader);
            t.start();
            Logger logger 
= Logger.getLogger(Log4jMain.class);
            logger.error(
"asdf");
            logger.info(
"asdf");
            logger.debug(
"asdf");
            logger.fatal(
"asdf");
                //hh是一个class,test方法里只有几个logger.info("aaa"),用于测试用,这东西可以去掉
            
new HH().test();

        }
 catch (Exception e) {
        }


    }

    
}
因为log4j提供的是 Writer,所以通过使用PipedWriter连接到PipedReader,并通过一个thread来处理PipedReader的数据就可以回显了。如果你需要的话可以将下面的System.out.println(scanner.nextLine());改成你需要显示的地方就行了。
import java.io.PipedReader;
import java.util.Scanner;

public class AaaThread extends Thread {
    PipedReader reader;

    
public AaaThread(PipedReader reader) {
        
this.reader = reader;
    }


    
public void run() {
        Scanner scanner 
= new Scanner(reader);
        
while (scanner.hasNext()) {
            System.out.println(scanner.nextLine());
        }

    }

}
posted @ 2008-06-06 09:31 小平 阅读(1196) | 评论 (0)编辑 收藏
这里制作一个引子,具体内容比较多,而且hibernate文档里的hql篇写的很详细
可以这么用:
List list = getHibernateTemplate().find("select new map(t1.c1,t2.c3) from table1 t1 ,table2 t2 where t1.c1=t2.c2");
这样的话list里的每个元素都是一个map,每个map里包含两个元素
注意:这里的table1和table2都是class名并不是真的表名,毕竟这是hql。除了可以用map还还支持list和自定义的bean。


posted @ 2008-04-17 17:05 小平 阅读(1867) | 评论 (0)编辑 收藏
DB2的Type-4驱动真的很诡异,配了两天没配上,发现是多引了一个包。就是他----“db2java.zip(db2java.jar)”只要有了他就算你已经引入了db2jcc.jar、db2jcc_license_cisuz.jar、db2jcc_license_cu.jar也没用。
不知道怎么回事,本以为多引就没错,没想到载这了。
顺便吧db2 type-4的配置方法贴下面:
jdbc:db2://ip:port/数据库
驱动名:com.ibm.db2.jcc.DB2Driver

我日他IBM!该死的IBM,我算是服了,配好的type-4驱动中文数据显示的全是乱码,准备切到type-2上试试,结构还是不行,查来查去是数据库pagecode的事,数据库的字符集改成gbk,客户端的pagecode也改成跟数据库一样的,ODBC算是能用了,type-2也能用了,然后又用type-4一试!连不上了!说字符集不匹配,上网一查说要使用IBM专用的JDK,我日了,换了IBM的JDK,配好环境变量eclipse又不能用了!我算是被IBM搞死了,一气之下也不准备再尝试type-4了。
我这里用的IBM JDK1.4,db2 V8
posted @ 2008-04-17 16:51 小平 阅读(2465) | 评论 (3)编辑 收藏

近日抽风,想了解以下java与串口并口通讯的问题,上网查了半天,找到了sun几年前的一个破包,comm.jar

2.0版的,遇到一个比较奇怪的问题,这个包里的demo程序用cmd可以运行,但是用eclipse编译就不能运行,一直以为是dll库和配置文件的问题,几乎将两个文件copy到了系统中全部可能出现的地方都没有解决。百般无奈之下,找到了http://blog.csdn.net/djsl6071/archive/2007/04/25/1583979.aspx这个博客,下载了rxtx把问题搞定了。
posted @ 2008-04-17 16:40 小平 阅读(551) | 评论 (0)编辑 收藏
如果RMI客户端链接补上服务器可能是以下情况导致的:
1、网络不通
2、端口占用
3、防火墙(客户端机器的防火墙和服务器端的防火墙都有可能)
4、服务器端所在机器安装了linux虚拟机,或者使用的linux或者unix系统
排除办法:
前三种情况都很好解决,主要是最后一个,需要在rmi服务启动时加上一句
java  -Djava.rmi.server.hostname=localhost ……
其中localhost可以强制定义为机器的IP地址 
posted @ 2008-02-15 14:11 小平 阅读(863) | 评论 (0)编辑 收藏
       为了满足将plugin工程打成jar包,但是spring的配置文件不打进jar包的需求。很多时候我们为了可以方便手工配置spring的一些信息,而不用将jar解压而从新压缩,我们需要把Spring的配置文件放在plugin的jar包外这时,如果没有正确的使用spring的Resource就不能加载spring的配置文件,经过多次尝试终于找到一个比较合适的方法,与大家交流。
public static BeanFactory getFactory() {
        
if (factory == null{
            FileSystemResource resource 
= new FileSystemResource("appcontextclient.xml");
            factory 
= new XmlBeanFactory(resource);
        }

        
return factory;

    }

        将appcontextclient.xml文件放到工程根目录下,发布时将appcontextclient.xml放入到你的eclipse的安装目录即可(与eclipse的exe执行文件相同的位置),如果需要可在appcontextclient.xml文件前加入相关的路径来更改你的目录(但是有可能在调试过程中必须要把appcontextclient.xml文件放到你的eclipse IDE的安装目录里,因为大部分时间我们的eclipse IDE是何 workspace分开存放的,这样我们在调试的时候非常别扭,要到IDE里去修改配置文件)。
        以上方法并不是唯一的,只是我感觉用起来比较合适的,这样在调试时既可以保证appcontextclient.xml文件在工程目录范围内,有可以在发布时使文件保持在安装目录而不是运行环境的workspace的临时目录里。
        同时介绍几个方法可以eclipse方法获得eclipse工具的几个重要路径(注:"IDE"为我的plugin工程的PLUGIN_ID)
        Platform.getInstallLocation().getURL()                                                 
        file:/F:/tools/java/eclipse/eclipse-SDK-3.3-win32/eclipse/             
        这是我的eclipse IDE的安装目录
            
        Platform.getLocation()                                                                        
        D:/runtime-IDE.product                                                               
        这是我调试插件时生成的临时运行环境目录,是在调试IDE工程时生成的,就是发布时插件所属eclipse运行环境的WorkSpace目录
             
        Platform.getInstanceLocation().getURL()                                             
        file:/D:/runtime-IDE.product/                                                       
         这个跟上面的一样
             
        Platform.getLocation()                                                                        
        D:/runtime-IDE.product                                                              
         这个跟上面的也一样
        
        Platform.getLogFileLocation()                                                             
        D:/runtime-IDE.product/.metadata/.log                                         
        运行环境的日志文件路径,发布时插件所属eclipse运行环境的WorkSpace目录下的/.metadata/.log 
         
        Platform.getStateLocation(Platform.getBundle("IDE"))               
        D:/runtime-IDE.product/.metadata/.plugins/IDE                           
        运行环境中IDE的一个临时目录,发布时插件所属eclipse运行环境的WorkSpace目录下/.metadata/.plugins/IDE
             
        Platform.getUserLocation()                                                       
        file:/C:/Documents and Settings/XX/user                                     
         这是我的文档的路径(把用户名X掉,哈哈)

        Platform.getBundle("IDE").getLocation()                                    
        update@D:/WorkSpace/IDE/                                                     
        我的IDE工程的路径,对应发布时插件的jar本身,在这个目录下的文件将全部包含在发不得jar里。

        Platform.getConfigurationLocation().getURL()       
        file:/D:/WorkSpace/.metadata/.plugins/org.eclipse.pde.core/IDE.product/  
        eclipse IDE 自己建的目录

        eclipse 本身也有很多加载资源文件的方法可以在org.eclipse.core.runtime.Platform这个类里找到,具体的就请大家找找API吧
posted @ 2008-01-05 21:35 小平 阅读(1996) | 评论 (0)编辑 收藏
应要求在此提供ibatis批量插入demo下载,谢谢大家的关注,不过对于一些人的不礼貌行为我非常痛心。由于工作地点不能上网,不能上网,不能及时回复大家的留言我深表道歉。下载
posted @ 2007-12-27 19:52 小平 阅读(3393) | 评论 (9)编辑 收藏
此问题网上大部分解决方法是这样的:
1.网上邻居->本地连接->属性->internet协议(TCP/IP)->属性->高级->wins标签->去掉启用LMhosts查询前的勾.
2.控制面版->windows防火墙->高级标签->本地连接设置->服务的标签里勾选安全Web服务器(HTTPS)即可
但是我的机器按照上面操作apache服务仍然不可以使用,于是索性将服务中的Windows Firewall/Internet Connection Sharing (ICS的服务关掉了,发现问题解决了,apache可以用了。对于安全问题可以选择第3方的防火墙来解决。
注意:费尔防火墙好像和apache冲突,也会导致WSASocket failed to open the inherited socket
posted @ 2007-10-21 14:53 小平 阅读(1441) | 评论 (1)编辑 收藏
      今天用sun的jdk调的没有一点问题的数据抽取程序,方放到AIX上后不能用了,oralce报出向一个字段中插入了过长的数据,可是程序在几天前还是没有问题的,后来分析可能是字符集导致的,因为前几天修改过informix数据库的字符集由8859-1转为了zh_cn.gb18030-2000,但解决过程异常艰难,后来吧informix的url改为<value>jdbc:informix-sqli://xx.xx.xx.xx:8888/XXXX:informixserver=whcspdev;DB_LOCALE=zh_cn.gb18030-2000;CLIENT_LOCALE=zh_cn.UTF8(原为zh_cn.gb18030-2000);NEWCODESET=gb18030,gb18030-2000,5488,utf8</value>就可以了。后来猜测了一下原因:
1、oracle数据库的jdbc驱动是是自动将数据库的数据转为unicode格式,这可能跟java的String默认为unicode有关,为了让大家方便操作,
2、sun jdk的String在初始时用的是Unicode格式,ibm的jdk应该也是,但是有一点,sun的jdk在通过informix jdbc驱动取数据时不会将数据转成其他字符集,而是仍然使用Unicode,而IBM的则是通过CLIENT_LOCALE=zh_cn.gb18030-2000配置将数据格式转为了zh_cn.gb18030-2000。
所以在oracle作insert的时候就会由于字符集不匹配而报错
posted @ 2007-07-18 19:23 小平 阅读(984) | 评论 (2)编辑 收藏

       前两天遇到为org.eclipse.jface.text.TextViewer添加undo、redo 并添加Ctrl+z,与Ctrl+y功能这个问题,搜遍了国内网站,也没有个好结果,终于多天后在一个国外的svn服务器上找到了一段代码,解决了问题
1、为TextViewer添加TextViewerUndoManager来管理记录

protected TextViewer textViewer;
     
protected TextViewerUndoManager undoManager;
     
      
//20是保存记录的数量。
     undoManager = new TextViewerUndoManager(20);
     
     
//绑定对textViewer控件的数据进行管理
     undoManager.connect(textViewer);
     textViewer.setUndoManager(undoManager);


2、添加Ctrl+z,与Ctrl+y事件

StyledText styledText = textViewer.getTextWidget();
styledText.addKeyListener(
new KeyListener( ) {
            
public void keyPressed( KeyEvent e )
            
{
                
if ( isUndoKeyPress( e ) )
                
{
                    textViewer.doOperation( ITextOperationTarget.UNDO );
                }

                
else if ( isRedoKeyPress( e ) )
                
{
                    textViewer.doOperation( ITextOperationTarget.REDO );
                }

            }

            
private boolean isUndoKeyPress( KeyEvent e )
            
{
                
// CTRL + z
                return ( ( e.stateMask & SWT.CONTROL ) > 0 )
                
&& ( ( e.keyCode == 'z' ) || ( e.keyCode == 'Z' ) );
            }

            
private boolean isRedoKeyPress( KeyEvent e )
            
{
                
// CTRL + y
                return ( ( e.stateMask & SWT.CONTROL ) > 0 )
                
&& ( ( e.keyCode == 'y' ) || ( e.keyCode == 'Y' ) );
            }

            
public void keyReleased( KeyEvent e )
            
{
                
// do nothing
            }

        }
);
posted @ 2007-07-16 10:49 小平 阅读(1843) | 评论 (3)编辑 收藏
        到一个这东西都写到3了,针对上回说到30000条数据的批量插入工作。30000条数据的批量插入在一个事务里处理固然是快,但是这只是测试环境,30000条数据在数据库的缓存里必然对数数据库的缓存和锁数量都是一个大的挑战,固在新的程序中我们使用了分批事务提交的方式,这样为了保持数据的正确行就只能人为控制数据库中已被插入的数据是否delete掉。另外,使用Batch块提交会引发一个问题就是,如果batch块中发生了异常,我们得不到异常数据的行号即任何信息,所以只能是鱼和熊掌不可兼得(我已关注过insert方法中返回pk的方法了,但好像在batch中他反回不了出错的行号,也许是我没有找到方法,如有人有好方法请共享一下,在这里表示感谢),大家酌情考虑吧,只能到到自己需要的平衡点了。
      建议:如果对数据的准确性毋庸置疑的话就是用batch处理。如果不能确定准确性的话,如果对那条数据出错无所谓的话就也可以用batch,但是非要返回出错行号的话就不要用batch了,直接在外面套用一个事务,然后try catch一下,处理一下行号。
posted @ 2007-06-28 21:32 小平 阅读(3282) | 评论 (4)编辑 收藏
今天发生了ORA-01461 :can bind a LONG value only for insert into a LONG ...到处查询发现是一个字段中的中文内容导致,仔细分析了一下原因,是因为jdk1.5的String类型为utf-16编码方式,而jdk1.4为utf-8,通过在oracle网上查询10g的jdbc驱动有两个版本,旧版的不持jdk1.5,只支持jdk1.4,通过换jdbc驱动问题解决。
posted @ 2007-06-20 10:53 小平 阅读(2796) | 评论 (0)编辑 收藏
1、上回的心得中我强调了startBatch()的批处理的作用,但是其中的使用是个错误用法,并没有发挥出startBatch()的实力,对此给与观众的误导我将在此表示到欠,并贴出正确的用法
public class LocalDaoImpl extends SqlMapClientDaoSupport implements LocalDao {

    
public void insertBuNaTaxBatLst(final PaginatedList list)
    
{
         getSqlMapClientTemplate().execute(
new SqlMapClientCallback() {
                
public Object doInSqlMapClient(SqlMapExecutor executor)
                        
throws SQLException {
                    executor.startBatch();
                    
// do some iBatis operations here
                    for(int i=0,count=list.size();i<count;i++)
                    
{    
                        executor.insert(
"insertBuNaTaxBatLst", list.get(i));
                        
if (i % 50 == 0{
                            System.out.println(
"----" + i);//没有意义只为测试
                        }

                    }

                    executor.executeBatch();
                    
return null;
                }

            }
);
    }


}
这样才能利用上startBatch()威力。
2、注意ibatis的事物默认情况下是自动提交的,如果发现速度上有问题可以留意一下,ibatis只有在显示的声明事物管理的情况下才自动将事物管理改为不自动方式。
3、还是startBatch(),据我测试分析这个鬼东西只有在executeBatch(),才把所有的语句提交到数据库,在提交之前缓存中保留了大量的sql语句和数据对象,很有可能out of memony,对此要留意,可以在大量数据要做插入时,分批用Batch,如:有40000条数据可将其分为4个Batch块,让后将这4个Batch用一个事物提交以保证数据完整性。
注:最近在做数据抽取项目,愿与大家沟通心得
posted @ 2007-05-30 21:46 小平 阅读(5942) | 评论 (6)编辑 收藏

程序功能:
使用ibatis+spring将oracle数据库中的tfile表中的数据抽取到db2数据库的tfile表,这两个表的结构相同。

测试环境:
celeron M 1.4/512M/mysql 5.0数据库
代码:

public static void main(String[] args) {
        
// TODO Auto-generated method stub
        ClassPathResource resource = new ClassPathResource(
                
"applicationContext.xml");
        BeanFactory factory 
= new XmlBeanFactory(resource);
        TFileDAO tFileDao 
= (TFileDAO) factory.getBean("tfile");

        TFileDAO test2FileDao 
= (TFileDAO) factory.getBean("test2tfile");
        
//获取全部数据
        List list = tFileDao.getAll();
        
//开启事务
        DataSourceTransactionManager txm = (DataSourceTransactionManager) factory
                .getBean(
"test2transactionManager");
        DefaultTransactionDefinition def 
= new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status 
= txm.getTransaction(def);
        
try {
            test2FileDao.getSqlMapClient().startBatch();
            
for (int i = 0, count = list.size(); i < count; i++{
            
//插入数据
                test2FileDao.insert((TFile) list.get(i));
            }

            test2FileDao.getSqlMapClient().executeBatch();// 这两句有问题,请见Spring+ibatis心得2!
        }
 catch (Exception e) {
            txm.rollback(status);
            System.out.println(e);
        }

        txm.commit(status);
        System.out.println(list.size());
    }
1、保证使用长事务,不要在每个插入都事务提交,这样性能可以有很大幅度的提升
2、使用 test2FileDao.getSqlMapClient().startBatch();
              test2FileDao.getSqlMapClient().executeBatch();
             可以发起jdbc对批量数据插入的优化与自动代码压缩功能。

      结语:这次使用ibatis在同样的硬件、数据库、数据条数的环境下测试,在不起用batch,所有数据库,数据池特性均使用默认设置情况下使用19秒,并且使用一次性将数据读入内存的方式,效果优于hibernate,所以真信优化后的程序应该比hibernate效率更高。但是从程序编写方面来讲,hibernate省去了过多的代码,可以让程序员更轻松些。
posted @ 2007-04-26 19:54 小平 阅读(3195) | 评论 (1)编辑 收藏

程序功能:
使用hibernate+spring将oracle数据库中的tfile表中的数据抽取到db2数据库的tfile表,这两个表的结构相同。(原本要使用一些Spring的特性,但是程序改来改去发现Spring特性一个都没用上,实际上完全可以由hibernate创建两个sessionFactory完成)
测试环境:
celeron M 1.4/512M/mysql 5.0数据库
代码:

public void save() {
  Session session
= fileDAO.getDataSession();
  Session session2
= fileDAO2.getDataSession();
  Transaction tx 
=session2.beginTransaction();
  
int count=0;
  List list 
=fileDAO.getList(session, count);
  
while(list.size()!=0)
  
{
   
for(int i=0,num =list.size();i<num;i++)
   
{
    session2.save(list.get(i));
    session.evict(list.get(i));
    
if(num%50==0)
    
{
     session2.flush();
     session2.clear();
    }

   }

   count
= count+500;
   list 
=fileDAO.getList(session, count);
   
  
// System.out.println(count);
   
  }

  tx.commit();
  session.close();
  session2.close();
}

配置文件:

<prop key="hibernate.jdbc.batch_size">50</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>

 

1、为保证不会出现内存溢出
   hibernate.jdbc.batch_size 设为 20-50
   并在代码中没隔50个insert后手工清理数据 
     

 if(num%50==0)
    
{
     session2.flush();
     session2.clear();
    }

2、为保证减少二级缓存导致的过多的内存开销关,闭二级缓存
  hibernate.cache.use_second_level_cache 设为false
3、保证使用长事务,不要在每个插入都事务提交,这样性能可以有很大幅度的提升(由于原先配的事务没有正常运行,在初次测试时此程序插入4万条数据用了12分钟,使用了长事务后仅为34秒)
4、使用ScrollableResults(提供了数据库的游标特性)然后插入的效果好像要优于分批抓取分批插入的效果,(4万条数据,用ScrollableResult耗时29秒)但网上有人声称批量抓取插入的效果要好可能在远程数据库的情况下批量抓取的可靠性更高一点的原因。这一点我询问过公司里做数据库比较好的人,批量处理数据是要使用游标处理的。就游标而言分为动态游标,静态游标,动态游标慢于静态游标,静态游标慢于静态查询,但是如果用分批抓取数据的话就涉及到数据分段截取,为保证每次分段截取时数据的正确性,应该要预先对数据处理,所以批量抽取数据的速度可能会慢一些。以下为使用ScrollableResult的程序
  

Session session= fileDAO.getDataSession();
  Session session2
= fileDAO2.getDataSession();
  Transaction tx 
=session2.beginTransaction();
  ScrollableResults tFiles 
= session.createQuery(
    
"from TFile as model ").setCacheMode(CacheMode.IGNORE).scroll(ScrollMode.FORWARD_ONLY);
  
int count=0;
  
while(tFiles.next())
  
{
   session2.save(tFiles.get(
0));
   
if(++count%50==0)
    
{
     session2.flush();
     session2.clear();
    }

  }

  tx.commit();
  session.close();
  session2.close();
posted @ 2007-04-24 19:30 小平 阅读(1787) | 评论 (0)编辑 收藏
1、定义静态的StatusLine文本
     WorkbenchWindowAdvisor 类中的preWindowOpen()方法加入
             configurer.setShowStatusLine(true);//显示状态栏
     ApplicationActionBarAdvisor类中增加
              protected void fillStatusLine(IStatusLineManager statusLine) {
              super.fillStatusLine(statusLine); 
              StatusLineContributionItem statusItem = new StatusLineContributionItem("DAStatus",50);
              statusItem.setText("状态栏:测试");
              statusLine.add(statusItem);

     }
将在状态栏中显示:“状态栏:测试”
2、定义动态的StatusLine文本
     WorkbenchWindowAdvisor 类中的preWindowOpen()方法加入
              configurer.setShowStatusLine(true);
      
      在要调用状态栏的class里加入下面方法
     private void showStatusMessage(String msg) {
               WorkbenchWindow workbenchWindow = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();
               IStatusLineManager lineManager = workbenchWindow.getStatusLineManager();
               StatusLineContributionItem statusItem = new StatusLineContributionItem("DAStatus",50);
               statusItem.setText(msg);
                lineManager.add(statusItem);
  }
         使用listener来调用showStatusMessage(String msg)即可。
     
posted @ 2007-04-09 15:53 小平 阅读(1356) | 评论 (1)编辑 收藏
<!-- 前置数据源MCP Դ -->
<bean id="dataSourceMcp" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  
<property name="driverClassName">
    
<value>com.informix.jdbc.IfxDriver</value>
  
</property>
  
<property name="url">
    
<value>jdbc:informix-sqli://192.168.102.31:8888/csptestdb:informixserver=whcspdev;db_locale=zh_CN.gb</value>
  
</property>
  
<property name="username">
    
<value>csptest</value>
  
</property>
  
<property name="password">
    
<value>csptest</value>
  
</property>
</bean>
程序
ClassPathResource resource = new ClassPathResource("resource/appcontextserver.xml");
            factory 
= new XmlBeanFactory(resource);
BasicDataSource o 
= (BasicDataSource) factory.getBean("dataSourceMcp")
o就是存放数据库信息的实例
posted @ 2007-04-09 15:41 小平 阅读(864) | 评论 (0)编辑 收藏
<2007年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

常用链接

留言簿(2)

随笔分类

随笔档案

framework

j2me

java

linux

web

其他

友情链接

素材

最新评论

阅读排行榜

评论排行榜