每日一得

不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速开发
最近关心的内容:SSH,seam,flex,敏捷,TDD
本站的官方站点是:颠覆软件

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  220 随笔 :: 9 文章 :: 421 评论 :: 0 Trackbacks

#

碰到一个奇怪的问题,Spring在启动的时候得listener提示启动失败,打开log也没有任何信息,最后把log4j打开 :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
        
<layout class="org.apache.log4j.PatternLayout">
            
<param name="ConversionPattern"
                   value
="%p - %C{1}.%M(%L) | %m%n"/>
        
</layout>
    
</appender>

    
<logger name="org.apache">
        
<level value="WARN"/>
    
</logger>


    
<logger name="net.sf.hibernate">
        
<level value="WARN"/>
    
</logger>

    
<logger name="org.springframework">
        
<level value="DEBUG"/>
    
</logger>
    
<!--
    <logger name="org.appfuse">
        <level value="DEBUG"/>
    </logger>
-->
    
<root>
        
<level value="DEBUG"/>
        
<appender-ref ref="CONSOLE"/>
    
</root>

</log4j:configuration>

提示说applicationContext.xml的编码有问题,最后改为UTF-8解决
posted @ 2006-10-23 10:57 Alex 阅读(1368) | 评论 (0)编辑 收藏

打印可以用控件实现,保存为excel也可以用POI实现,不过如果仅仅是对当前页面的指定区域作打印或者Excel导出可以用js实现,还是挺简单的.

保存为Excel:

function saveAsExcel(HeadName, DivName) {
            
var s = "<center>" + HeadName + "</center>" + "\r\n";
            s 
+= DivName.innerHTML;
            
var xlsWindow = window.open("""_blank""width=1,height=1,scrollbars=no,toolbar=no");
            xlsWindow.document.write(s);
            xlsWindow.document.close();
            xlsWindow.document.execCommand('Saveas', 
true, '%homeDrive%\\Data.xls')
            xlsWindow.close();
        }


打印当前页面:

function PrintDataSoure(HeadName1,HeadName2,HeadName3,DivName,TailName1) {
  
var oldBody=document.body.innerHTML;
  
var Div1=DivName.innerHTML;
  
var css = '<style type="text/css" media=all>+
  'p { line
-height: 120%}' +
  '.fhead {   font
-size: 9pt; text-decoration: none; color: 104A7B}' +
  '.ftitle { line
-height: 120%; font-size: 18px; color: #000000}' +
  'td { font
-size: 10px; color: #000000}' +
  '
</style>' ;

  
var body ='<table width="640" border="0" cellspacing="0" cellpadding="5">+
  ' 
<tr> ' +
  ' 
<td class="fbody">+
  ' 
<b><div align="center">'+'<font size="+1" class=fhead>'+ HeadName1 + '</div>'+'</font></b>'+
  ' 
<b><div align="center">'+'<font size="+1" class=fhead>'+ HeadName2 + '     ' + HeadName3 +'</div></font></b>'+
  ' 
</td>+
  ' 
</tr>+
  ' 
<tr> ' +
  ' 
<td class="fbody">+
  ' 
<div align="center" class=ftitle>+ Div1 + '</div>'+
  ' 
<b><div align="right">'+'<font size="+1" class=fhead>'+ '      </div>'+'</font></b>'+
  ' 
<b><div align="right">'+'<font size="+1" class=fhead>'+ TailName1 + '</div>'+'</font></b>'+
  ' 
</td>+
  ' 
</tr>+
  '
</table>';
document.body.innerHTML 
= '<center>+ css + body +'<OBJECT classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2" height=0 id=wb name=wb width=0></OBJECT>'+'</center>';
wb.execwb(
6,6);
document.body.innerHTML
=oldBody;
}




posted @ 2006-10-21 12:19 Alex 阅读(3127) | 评论 (0)编辑 收藏

     摘要: key words:Spring,jdbcTemplate 注:因为Spring是以后的一个趋势,Hibernate的集成已经很好了,对于单独的jdbc的操作用DBUtils感觉已经没有什么必要,不如全部转到Spring的jdbc支持,从成本来考虑似乎更合适。 本文转自 这里 ...  阅读全文
posted @ 2006-10-16 16:28 Alex 阅读(2729) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2006-10-10 11:09 Alex 阅读(2031) | 评论 (3)编辑 收藏

Facade用的非常的广了,以前刚接触的时候有个误解,总觉得Facade是简单的,而它后面的支撑服务是复杂的,对于客户来说却是简单的,现在来看,不完全对,或者说只是说对了一半,因为有时候恰恰是Facade是复杂的.

我们举一个例子,比如发送短信,我们一般就定义一个MessageService的服务类,里面只提供一个方法就行了,sendToUser(String phone,String content)
但是到了客户端的时候有了自己的 "方言",比如它不是关心一个抽象的用户,它只知道向教师发送短信,或者向学生发送短信,或者向家长发送短信。

示例如下:

facade.png
由图中可以看到,Facade的内容非常丰富,而支撑它的服务类却很简单,在开发过程中我们一般先实现通用的ServiceA,然后根据进一步的需求做一个面向具体复杂的Facade.



在Spring提供的sample里发现一个小技巧,就是Facade和ServiceA都是接口,然后提供一个实现二者的支撑类:


public class PetStoreAnnotationImpl implements PetStoreFacade, OrderService {

    
private AccountDao accountDao;

    
private CategoryDao categoryDao;

    
private ProductDao productDao;

    
private ItemDao itemDao;

    
private OrderDao orderDao;


    
//-------------------------------------------------------------------------
    
// Setter methods for dependency injection
    
//-------------------------------------------------------------------------

    
public void setAccountDao(AccountDao accountDao) {
        
this.accountDao = accountDao;
    }

    
public void setCategoryDao(CategoryDao categoryDao) {
        
this.categoryDao = categoryDao;
    }

    
public void setProductDao(ProductDao productDao) {
        
this.productDao = productDao;
    }

    
public void setItemDao(ItemDao itemDao) {
        
this.itemDao = itemDao;
    }

    
public void setOrderDao(OrderDao orderDao) {
        
this.orderDao = orderDao;
    }


    
//-------------------------------------------------------------------------
    
// Operation methods, implementing the PetStoreFacade interface
    
//-------------------------------------------------------------------------

    
public Account getAccount(String username) {
        
return this.accountDao.getAccount(username);
    }

    
public Account getAccount(String username, String password) {
        
return this.accountDao.getAccount(username, password);
    }

    
public void insertAccount(Account account) {
        
this.accountDao.insertAccount(account);
    }

    
public void updateAccount(Account account) {
        
this.accountDao.updateAccount(account);
    }

    
public List getUsernameList() {
        
return this.accountDao.getUsernameList();
    }

    
public List getCategoryList() {
        
return this.categoryDao.getCategoryList();
    }

    
public Category getCategory(String categoryId) {
        
return this.categoryDao.getCategory(categoryId);
    }

    
public List getProductListByCategory(String categoryId) {
        
return this.productDao.getProductListByCategory(categoryId);
    }

    
public List searchProductList(String keywords) {
        
return this.productDao.searchProductList(keywords);
    }

    
public Product getProduct(String productId) {
        
return this.productDao.getProduct(productId);
    }

    
public List getItemListByProduct(String productId) {
        
return this.itemDao.getItemListByProduct(productId);
    }

    
public Item getItem(String itemId) {
        
return this.itemDao.getItem(itemId);
    }

    
public boolean isItemInStock(String itemId) {
        
return this.itemDao.isItemInStock(itemId);
    }

    
public void insertOrder(Order order) {
        
this.orderDao.insertOrder(order);
        
this.itemDao.updateQuantity(order);
    }

    
public Order getOrder(int orderId) {
        
return this.orderDao.getOrder(orderId);
    }

    
public List getOrdersByUsername(String username) {
        
return this.orderDao.getOrdersByUsername(username);
    }

}


看起来似乎不错,不过仔细想想个人认为还是不是太好,总的感觉就是层次不清晰,因为很多时候Facade和Service之间是被服务与服务的关系,所以理当分开。 同时,这个类有点倾向于"万能类"了,能分还是分开好.这和我们以前提到的dao又背离过来了(以前我们提倡一个业务一个dao,现在觉得只用一个通用的dao更合适),这个并不矛盾,具体问题具体看待.

欢迎各位拍砖.
posted @ 2006-10-09 22:27 Alex 阅读(1354) | 评论 (2)编辑 收藏

设计模式之Visitor

板桥里人 http://www.jdon.com 2002/05/05(转载请保留)

模式实战书籍《Java实用系统开发指南》

Visitor访问者模式定义
作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作.

在Java中,Visitor模式实际上是分离了collection结构中的元素和对这些元素进行操作的行为.

为何使用Visitor?
Java的Collection(包括Vector和Hashtable)是我们最经常使用的技术,可是Collection好象是个黑色大染缸,本来有 各种鲜明类型特征的对象一旦放入后,再取出时,这些类型就消失了.那么我们势必要用If来判断,如:


Iterator iterator = collection.iterator()
while (iterator.hasNext()) {
   Object o = iterator.next();
   if (o instanceof Collection)
      messyPrintCollection((Collection)o);
   else if (o instanceof String)
      System.out.println("'"+o.toString()+"'");
   else if (o instanceof Float)
      System.out.println(o.toString()+"f");
   else
      System.out.println(o.toString());
}
在上例中,我们使用了 instanceof来判断 o的类型.

很显然,这样做的缺点代码If else if 很繁琐.我们就可以使用Visitor模式解决它.

如何使用Visitor?
针对上例,定义接口叫Visitable,用来定义一个Accept操作,也就是说让Collection每个元素具备可访问性.

被访问者是我们Collection的每个元素Element,我们要为这些Element定义一个可以接受访问的接口(访问和被访问是互动的,只有访问者,被访问者如果表示不欢迎,访问者就不能访问),取名为Visitable,也可取名为Element。

public interface Visitable
{
   public void accept(Visitor visitor);
}

被访问的具体元素继承这个新的接口Visitable:

public class StringElement implements Visitable
{
   private String value;
   public StringElement(String string) {
      value = string;
   }

   public String getValue(){
      return value;
   }


   //定义accept的具体内容 这里是很简单的一句调用
   public void accept(Visitor visitor) {
      visitor.visitString(this);
   }
}


上面是被访问者是字符串类型,下面再建立一个Float类型的:

public class FloatElement implements Visitable
{
   private Float value;
   public FloatElement(Float value) {
      this.value = value;
   }

   public Float getValue(){
      return value;
   }


   //定义accept的具体内容 这里是很简单的一句调用
   public void accept(Visitor visitor) {
      visitor.visitFloat(this);
   }
}


我 们设计一个接口visitor访问者,在这个接口中,有一些访问操作,这些访问操作是专门访问对象集合Collection中有可能的所有类,目前我们假 定有三个行为:访问对象集合中的字符串类型;访问对象集合中的Float类型;访问对象集合中的对象集合类型。注意最后一个类型是集合嵌套,通过这个嵌套 实现可以看出使用访问模式的一个优点。

接口visitor访问者如下:

public interface Visitor
{

   public void visitString(StringElement stringE);
   public void visitFloat(FloatElement floatE);
   public void visitCollection(Collection collection);

}

访问者的实现:

public class ConcreteVisitor implements Visitor
{
   //在本方法中,我们实现了对Collection的元素的成功访问
   public void visitCollection(Collection collection) {
      Iterator iterator = collection.iterator()
      while (iterator.hasNext()) {
         Object o = iterator.next();
         if (o instanceof Visitable)
            ((Visitable)o).accept(this);
      }
   }

   public void visitString(StringElement stringE) {
      System.out.println("'"+stringE.getValue()+"'");
   }
   public void visitFloat(FloatElement floatE){
      System.out.println(floatE.getValue().toString()+"f");
   }

}

在上面的visitCollection我们实现了对Collection每个元素访问,只使用了一个判断语句,只要判断其是否可以访问.

StringElement只是一个实现,可以拓展为更多的实现,整个核心奥妙在accept方法中,在遍历Collection时,通过相应的accept方法调用具体类型的被访问者。这一步确定了被访问者类型,

如果是StringElement,而StringElement则回调访问者的visiteString方法,这一步实现了行为操作方法。

客户端代码:

Visitor visitor = new ConcreteVisitor();

StringElement stringE = new StringElement("I am a String");
visitor.visitString(stringE);

Collection list = new ArrayList();
list.add(new StringElement("I am a String1"));
list.add(new StringElement("I am a String2"));
list.add(new FloatElement(new Float(12)));
list.add(new StringElement("I am a String3"));
visitor.visitCollection(list);

客户端代码中的list对象集合中放置了多种数据类型,对对象集合中的访问不必象一开始那样,使用instance of逐个判断,而是通过访问者模式巧妙实现了。

至此,我们完成了Visitor模式基本结构.

使用Visitor模式的前提
使用访问者模式是对象群结构中(Collection) 中的对象类型很少改变。

在两个接口Visitor和Visitable中,确保Visitable很少变化,也就是说,确保不能老有新的Element元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便.

如果对象集合中的对象集合经常有变化, 那么不但Visitor实现要变化,Visistable也要增加相应行为,GOF建议是,不如在这些对象类中直接逐个定义操作,无需使用访问者设计模式。

但是在Java中,Java的Reflect技术解决了这个问题,因此结合reflect反射机制,可以使得访问者模式适用范围更广了。

Reflect技术是在运行期间动态获取对象类型和方法的一种技术,具体实现参考Javaworld的英文原文.
posted @ 2006-09-28 09:30 Alex 阅读(522) | 评论 (0)编辑 收藏

key words:软件设计 建模 UML

这篇文章以前就看到了,后来再想看的时候居然找不到了,感觉写的不错,作为想把软件开发往深里整地朋友有借鉴作用。

转自这里

前段时间把一个界面框架完成了,今天基于这个框架开发一个小模块,在这里把这个模块设计的全过程记录下来,希望大家讨论并指正。

一、起因

公 司交给我一个任务,为测试员写一个手机模拟界面,以方便她们的手机短信测试。过去她们都是用MC4J直接调用公司服务器的MBean服务来模拟进行测试, 以验证我们整个系统平台。这种测试主要是检查收发短信是否正常,而我的要做的工作就是,让她们在测试的时候更方便更直观。

二、需求

我和测试员陈MM(也就是软件的使用者)约定了一个时间,大家一起来讨论这个软件的需求。

1、首先,我大概了解了一下她们的测试工作,知道我要做个什么东东。

2、然后我回去思考了一下,再次找她详细了解其测试的具体步骤,并在一张白纸上以UML用例图的方式,记录下需求的功能。用例是什么?用例就是需求,就是你的软件应该具有的功能,当然用例图只是概括性的对功能进行了描述。

3、最后,我坐在我的电脑前开始用MagicDraw UML来画用例图(我不喜欢用Rose,那玩意太笨重了,界面友好性也不好)。在画用例图的时候,我发现了一些隐含的功能,这些是陈MM在和我做需求时没有考虑到的(注:开发者应该为用户挖掘隐含需求)。我和陈MM一一确定了这些我新发现的需求,最后得到如下的用例图。

(1)手机前台测试操作的用例图(说明:include是指某用例包含(include)子用例)

[用例]手机.jpg
 (2)后台管理
[用例]后台管理.jpg


三、界面设计

接下来是界面设计。既然是手机模拟,我很自然就拿我的motorola手机的操作界面来做参考。不过这里应该注意到,手机操作环境和电脑操作环境不尽相同(比如说电脑有鼠标,还有键盘可以输入文字),所以没有必要唯妙唯肖的完全模枋,还是以使用者操作方便为主。

界 面设计是很重要的一步,不要一上来就写程序,一定要先做到心中有个大概,否则返工的可能性就很大。而且,把界面拿出来给客户看,客户也就能做到心中有数, 还能尽早提出一些新需求和意见来。千万不要等到软件做完了再拿给客户看,到时客户看了如果要修改,那就做太多白费工了。

由于软件界面相对简单,陈MM基本没有提修改意见,但这不是个好兆头。不过极限编程就是要拥抱变化不是^_^。咱不怕她改,只要大致的界面她能定下来就行了。

界面我喜欢用Visio来画,当然也听说有人喜欢用VB来快速构建界面原型的,看个人喜好了。整个界面如下:
[界面设计]手机.jpg



这个是后台管理界面
[界面设计]号码管理.jpg



四、类图

类图反映了软件的数据模型。在设计数据模型,我参考了界面设计图和用例图,找出一个个的类。然后参照用例图的一个个功能,设计出了各类的属性和方法。设计初始的类图当然不可能很详细,但至少应该看到个大概。有错误不要紧,后期可以慢慢修正,但大体关系就算定下来了。

Neil(公司CTO,一个40岁左右的真正的资深程序员)说:看一个软件的设计主要看两个类:类图和时序图。类图确定了软件数据模型的静态关型,时序图则是数据模型的动态关系。

类图如下,看英文大致可以知道类/属性/方法的含义和作用了,就不一一介绍了。


[类图].jpg



五、时序图

时序图是本文最后一个图,时序图表明了用例图中各功能的实现方案,同时也反应了类图中各类的交互关系。以后程序的逻辑和时序图基本一致。不过,有些人会去画得很详细的时序图,详细到都快赶上伪代码级别了,我觉得这没必要。我把时序图看做反映自己思路的大概过程,所以也就画个大概。

我认为时序图要简洁易懂,这样以后你的后继维护者,拿到这个软件的时序图(当然也包括用例图、类图),就能明白你的大概设计思路。另外,画时序图也能整理自己的思路,同时还可以对类图的设计进行验证。在画这个时序图的过程中,我就纠正了在类图中的几处考虑不周的地方。

总结:时序图可以(1)整理思路(2)验证类的设计(3)是很好的软件文档,对维护者理解代码很有帮助。

这里仅给出其中几个时序图(实际上我也没有把用例都画完,有些类似的简单的,就忽略了)

(1)新增一个手机号码
[时序图]add phone number.jpg

(2)关机
[时序图]power off.jpg
(3)开机
[时序图]power on.jpg
(4)发送短信
[时序图]send message.jpg



到这里设计阶段就完成了,用时一天。下一步是编码,将应用TDD先写测试代码的方式来写代码,下次再介绍了。


作者简介

陈刚,广西桂林人,著作有《Eclipse从入门到精通》
您可以通过其博客了解更多信息和文章:http://www.ChenGang.com.cn
版权声明:本博客所有文章仅适用于非商业性转载,并请在转载时注明出处及作者的署名。

posted @ 2006-09-22 13:16 Alex 阅读(917) | 评论 (0)编辑 收藏

key words:软件架构师
转自here

现在软件架构师满天飞,是个写代码的都称自己为软件架构师,就象开个公司管上四五号人就给自己按个CEO头衔一样,着实让人好笑。于是到网上GOOGLE了一下看看软件构架师具体是个啥东东,有想做货真价实的构架师,就朝着那方向努力吧。网摘如下:

软件架构师的职责:将客户的需求转换为规范的开发计划及文本,并制定这个项目的总体架构,指导整个开发团队完成这个计划。

软件架构师的具体工作:
    (
1)在需求阶段,软件架构师主要负责理解和管理非功能性系统需求,比如软件的可维护性、性能、复用性、可靠性、有效性和可测试性等等,此外,架构师还要经常审查和客户及市场人员所提出的需求,确认开发团队所提出的设计;
    (
2)在需求越来越明确后,架构师的关注点开始转移到组织开发团队成员和开发过程定义上;
    (
3)在软件设计阶段,架构师负责对整个软件体系结构、关键构件、接口和开发政策的设计;
    (
4)在编码阶段,架构师则成为详细设计者和代码编写者的顾问,并且经常性地要举行一些技术研讨会、技术培训班等;
    (
5)随着软件开始测试、集成和交付,集成和测试支持将成为软件架构师的工作重点;
    (
6)在软件维护开始时,软件架构师就开始为下一版本的产品是否应该增加新的功能模块进行决策。
 
软件架构师的要求
      (
1)必须对开发技术非常了解,具有丰富的软件设计与开发经验,关键时候能对技术的选择作出及时、有效的决定。
      (
2)有良好的组织管理能力:沟通、领导、团队协作
      (
3)构件通信机制方面的知识:远程调用、JAVARMI、CORBA、COM/DCOM、各种标准的通信协议、网络服务、面对对象数据库、关系数据库等等

成长为软件架构师的几个阶段:
      (
1)构架师胚胎(程序员):语言基础、设计基础、通信基础等,内容包括java、c、c++、uml、RUP、XML、socket通信(通信协议)
      (
2)构架师萌芽(高级程序员):分布式系统组建等内容,包括分布式系统原理、ejb、corba、com/com+、webservice、网络计算机、高性能并发处理等
      (
3)构架师幼苗(设计师):透彻掌握设计模式,包括设计模式(c++版本、java版本)、ejb设计模式、J2EE构架、UDDI、软件设计模式等。此期间,最好能够了解软件工程在实际项目中的应用以及小组开发、团队管理
posted @ 2006-09-22 13:14 Alex 阅读(630) | 评论 (0)编辑 收藏

key words: DAO模式

今天在看一篇文章时提到了DAO,这个东西以前也经常接触,突然想回顾一下,于是打开Appfuse里看看dao模式(记忆中appfuse里就是很多的dao)

截图如下:
appfusedao.png

很清楚,左边的部分是基础模块,原意是想让右边的DAO和实现能够重用左边的,可是我找了半天也没看到需要重用左边的东西,因为在client调用的所有方法中都是明确的getUser或removeUser,就是没有getObject或者removeObject,那么不禁要问,左边的基础dao和它的实现还有什么意义呢?所以我的第一想法就是把左边的去掉得了,还好,果然有支持我想法的做法,打开springside,我们看到如下的结构:
截图2
springside.png
这里的做法更厉害,连interface也不要了,不过效果确实是很简洁,在bookmanager里完全重用了左边的基本方法 :
public Book get(Integer id) {
        
return (Book) super.get(id);
    }

    
public void save(Book book) {
        
super.save(book);
        logger.info(
"保存图书.图书详情:" + book.toString());
    }

    
public void remove(Integer id) {
        
super.remove(id);
        logger.info(
"删除图书.图书ID:" + id);
    }

这是一个更务实的做法,如果你的项目并不是那么那么的复杂完全可以这么做,当然要说其有什么缺点显然和没有了interface的天生属性决定了的,不可强求,若你对测试隔离面向接口以及你能想到的所有关于interface的好处,那就用你自己的方式吧。

现在我在想一个问题,难道appfuse里的继承的基本关于object的做法就没有地方可用了么?


其时正好碰到java视线这一篇文章有点相关,你可以参考一下:
用DAO模式有什么好处?


ps:
以前是一个基本的dao,然后n个业务dao继承于这个基本dao,现在提供一个通用dao,每个要用到的地方直接继承用就是了,更务实了!
不过,有一个小小的瑕疵,就是对于service中类似getUserByName或者getPeopleByEmail方法中需要提供给dao一个sql语句,从mvc的角度看,在service中看到了db层,有点不雅,不过综合来看这个还是可以或略,不要专牛角尖嘛  :)

posted @ 2006-09-21 16:05 Alex 阅读(2425) | 评论 (0)编辑 收藏

key words: VSS IDEA

vss实在是太恶心了,提交各东西还不支此右键,要是要在开发一段时间后提交多个不同的目录下的文件费死劲了,我压根不知道哪个文件还没有提交,Fuck Microsoft!

至少,我们还有IDEA  :)  在开发工具里提交的一个好处就是直观和简便.Let's go!

具体指导请看这里
你需要填写关于VSS的相关信息 ,截图如下:
vss.png

其中的vss project可能有点困难,属于vss自己的术语,你自己实际上是不知道的,方法是打开vss客户端,通过这个工具查找到你所在的项目的vss project到底是什么,右键项目名称,出现如下dialog
vss2.png

OK了

在IDEA里看看效果,截图如下:
vss3.png


Fine.
posted @ 2006-09-21 11:40 Alex 阅读(2994) | 评论 (3)编辑 收藏

key words :Oracle分页 视图

google了一下关于Oracle的分页方法,方法还不少,大多数效果差不多-有点恶心. 恶心也要作,不过后来就是大家都用得这种方式在我这里出现了新问题,奇怪的是怎么没有别人碰到?

String condition = " teacher_id = " + userId + " and school_id="+siteId;
sql 
=
   
" select * " +
   
" from your_table where " + condition +
   
" and rowid not in ( select rowid from your_table where" + condition +
   
" and rownum <= " + (pageIndex - 1* Constants.PAGE_NUMS + "" +
   
" and rownum <= " + Constants.PAGE_NUMS ;

现在的问题是我需要按照table的某个字段排序,于是改成如下:
String condition = " teacher_id = " + userId + " and school_id="+siteId;
sql 
=
    
" select * " +
    
" from your_table where " + condition +
    
" and rowid not in ( select rowid from your_table where" + condition +
    
" and rownum <= " + (pageIndex - 1* Constants.PAGE_NUMS + "order by id desc" +
    
" and rownum <= " + Constants.PAGE_NUMS + " order by id desc";

这个sql有问题么?
答案是可能有问题,也可能没有问题,因为据说在8i的Oracle版本之前都不行,实际上也不尽然,在我的9i和10g我得到的是同样的错误 "missing right parenthesis",还有一位兄弟估计是DBA建议我去metalink打一个patch,埃,动作太大了,不敢动。

问题还是要解决,试了下类似于select a.*,rownum r from (select * from table where ...) a where rownum < 10 等的方法,效果一样,就是不能加嵌套的order by
最后,用视图的方法间接解决问题,因为我要解决的问题实际就是按某个字段排序,那么在视图里先对table进行排序,再在视图的基础上作操作就OK了.

另,还有一种不错的实现方法,即用OracleCachedRowSet,分页也比较简单,有点类似于hibernate,由于时间关系没有时间去看,感兴趣的朋友可以看一下.


BTW: 对于视图可能rowid有问题,可以改成视图的某个主键替换

String condition = " teacher_id = " + userId + " and school_id="+siteId;
sql 
=
    
" select * " +
    
" from your_table where " + condition +
    
" and id not in ( select id from your_table where" + condition +
    
" and rownum <= " + (pageIndex - 1* Constants.PAGE_NUMS + "order by id desc) " +
    
" and rownum <= " + Constants.PAGE_NUMS + " order by id desc";



posted @ 2006-09-20 15:36 Alex 阅读(1677) | 评论 (3)编辑 收藏

转自 robin

Java本身是一种设计的非常简单,非常精巧的语言,所以Java背后的原理也很简单,归结起来就是两点:

1、JVM的内存管理

理解了这一点,所有和对象相关的问题统统都能解决

2、JVM Class Loader

理解了这一点,所有和Java相关的配置问题,包括各种App Server的配置,应用的发布问题统统都能解决

就像张无忌学太极剑,本质就是一圈一圈的画圆,你要是懂得了太极剑的本质,那么太极剑就那么一招而已,本身是很容易学的,只是难度在于你要能够举一 反三,化一式剑意为无穷无尽的剑招,这就需要一点悟性和不断的实践了;反过来说,如果学剑不学本质,光学剑招,你就是学会了1万招,碰到了第1万零1招, 还是不会招架,败下阵来。

技术世界本来就是丰富多彩,企图统一标准,实际上也做不到,但是世界本质其实并不复杂。学习技术,特别是某种具体的软件工具的时候,应该学会迅速把 握事物的本质,不要过多搅缠细节。软件工具应该为我所用,而不是我被工具所驾驭。当你具备了对整个J2EE架构的设计和实施的能力,你还会被具体的工具束 缚吗?哪种工具适合你的架构,你就用什么,哪种不适合你,你就抛弃它,软件皆臣服于你的脚下,而不是你被什么软件牵着鼻子走,到了这种程度,你难道还害怕 学习什么新的软件?

我自己也在一直朝着这个方向努力,在我心中,设计软件,架构是第一位的,采用什么技术要为架构服务。如果我发现什么技术对我的架构来说很重要,那么 我会花时间去学习,去钻研,就像我花时间去钻研ORM一样,如果我觉得什么技术对我的架构来说没有用,即使技术再火爆,我也不去碰它

总之要学会抓住本质,驾驭技术,而不是被技术所驾驭。当你掌握了本质原理,其实学什么都很快,毕竟都是相通的,我先看JDO,后看 Hibernate,其实两者就很类似,所以学得很快,以后如果有工作需要,要我学习别的ORM,那我也不会觉得有什么困难的,一样手到拿来。

更有说服力的是Unix类的操作系统,那就更相似了,只要抓住了Unix最本质的几点,例如shell命令和编程,文件系统结构和配置,系统启动原 理和过程,所有的Unix都是无师自通的。我自己会用Linux,FreeBSD,SCO Unix, Solaris,HP-UX 和 AIX等6种Unix,更体会到一通百通的道理。

拿刚出了光明顶密道的张无忌来说吧,(我很喜欢张无忌这个角色),他也没有练过什么武功,但是他已经把天下武学之本质:九阳神功 + 乾坤大挪移学会了,所以不管什么功夫,他都是看一遍就会,马上为我所用,看了空性用了一遍龙爪手,就会用龙爪手来破对方;和昆仑派打了一架,就会用昆仑剑 法和灭绝师太过招;七伤拳更是无师自通;太极拳也是看一遍就会。

总之,学习方法还是很重要,别被五花八门的技术给搞不清学习方向了。

posted @ 2006-09-20 12:12 Alex 阅读(445) | 评论 (1)编辑 收藏

转自portian

基本上一个应用程序里面的领域相关的模型里面需要3种对象:
1。值对象(Value Object),没有身份,内容表示一切,譬如我和weihello都去银行里面存取100大洋,那这个100RMB是一个值对象

2。实体对象(Entity),需要持久,不是按照内容,而是按照它的身份来区分,也就是说即使内容完全一样,也不是同一个对象。这个身份在内存 里面是它的实例地址,在数据库里面是关键字,最常见的就是OID.这个实体对象并不是纯数据,它处理本身的实体模型,例如Accout,它的 withDraw,它的子Account等等,它也处理自己和其他实体对象之间的关系,例如订单里面的订单行,都是应该在这个Account里面实现的, 而不应该有一个什么控制类。在一个Web应用程序里面,涉及到对象关系的一般只需要一个(或几个)DTOFactory负责所有对象的DTO和 Entity之间的组装和拆份,不需要专门的管理,这一部分也是和数据建模最相近的地方。
 
3。服务对象(Service),这是为我们提供服务的类,譬如银行里面服务员,她帮助我们把钱从一个账户转到另外一个账户,并记录相应的交易。

对象的作用是对它自己的内部状态负责,如果它需要存取很多其它对象的状态进行运算,那叫做特性忌妒,是要重构的。应该把这些代码移到那个持有这些状态的类里面



辨别一些名词:
1。VO:实际上很模糊,通常指ValueObject和ViewObject
2. ViewObject,界面展现需要的对象,如Struts的FormBean
3。Value Object,早期被作为ValueObject和Transfer Object的总称。实际上Value Object的真正意义在于它的内容,而不是身份
4。Transfer Object:数据传输对象,在应用程序不同层次之间传书对象,在一个分布式应用程序中,通常可以提高整体的性能
5。PO:也许就是Persistent Object,基本上就是Entity了
在不同的体系结构和实现方式里面,这些对象有可能重复,也有可能不重叠。如果你要做一个对所有的体系都能够方便移植的框架,那么每一种对象都需要 严格区分。例如JDO的PO不能作为TO,应为它不能脱离PM,譬如你可以选择用ViewObject(如Struts的FOrmBean)直接作为 TO,但在tapestry和Webwork里面就不合适了。但在很多时候,能够方便实用是最重要的,不要过度设计就是了。
posted @ 2006-09-20 09:53 Alex 阅读(402) | 评论 (1)编辑 收藏

key words: 如何做设计 设计步骤
转自robin

一。需求分析(抽象Use case + 分析Use case之间的关系)

分析软件需求,以用户的角度来使用软件,找出发生的scenerio,抽象成为一个一个Use Case,分析出Use Case之间的关系,这一步是非常重要的,这一步做好了,设计就成功了一半。Use Case的抽象有一些可以遵循的原则,这里不详细谈。

然后用语言描述每一个Use Case,描述用户使用一个Use Case发生的主事件流以及异常流。

这样就完成了需求分析阶段。

二。概要设计(找出实体 + 分析实体类之间的关系 + 提取控制类 + 画序列图)

接下来做概要设计,针对每个Use Case,读Use Case的描述,看事件流,找出所有的实体类,这也有一些可以遵循的原则,例如找出所有的名词,画表格排除等等方法。

然后分析实体类之间的关系,是包含,聚合还是依赖,是1:1,还是1:n,还是其他....,根据这些关系,就可以得出实体类和别的实体类想关联的属性,然后再找出每个实体类本身重要的属性。

然后再次分析Use Case的事件流,一方面check实体类的设计是否合理,另一方面你可以找出动词,分析对实体类的控制逻辑,这样就可以可以设计出业务控制类,一般你可 以一个实体类一个控制类,也可以业务逻辑相关的实体类由一个Facade Session Bean(非EJB含义)来统一控制,这里面的控制类的颗粒度就由你自己来掌握了。一般来说先可以设计一些细颗粒度的控制类,然后再按照模块,用粗粒度封 装细颗粒度的控制类,提供给Web层一个Facade。

然后你可以画序列图,就是用序列图来表达事件流,在这个过程中,你需要不断回到类图,给控制类添加方法,而序列图就是控制类的方法调用。

至此,你已经在Rose里面完成了概要设计,当然你不可能一次设计完善,会有很多次迭代,因此你不能一开始把类设计的太详细,只抓住主要的属性和方法,特别需要注意的是,是抽象的设计,不要用具体的编程语言来表达类。

三。实施(结合xdoclet和Schema工具自动生成代码)

然后你就可以抛开Rose了,转到Eclipse+Togehter里面,根据那些类,规划一下package层次,然后在Together里面进行类的详细设计,所有需要的属性一一写上,当然你还是不可能一下把所有的属性方法写全,不过没有关系,把重要的写好就行了。

然后类框架已经生成好了,给所有的实体类加上xdoclet,然后生成hbm,然后用Hibernate的ExportScheme生成DDL,运行一遍自动创建好所有的表。这样所有的实体相关类全部做好了。

你现在就集中精力把控制类那些方法里面的代码填写上就OK了,在这个过程,你会发现有些实体类缺属性,没有关系,加上属性,然后写好xdoclet,运行一遍,自动生成hbm,自动创建好表,然后继续写你的方法,也有可能你发现控制类缺方法,那么就加上。

基本上实体类就是getter/setter,和少量的实体相关方法,所有的控制逻辑都写在控制类里面。

最后你的软件就基本写好了,用Eclipse生成好一堆你的testCase运行测试,反复修改,除bug。

看看使用OOAD的设计思路,是多么的爽的事情阿!你只需要把精力放到Use Case的抽象,实体类的关系总结,控制类的归纳。而当你使用Eclipse+Together之后,你所需要写的代码只不过是控制类的方法实现代码,其 他的都已经生成好了。另外可能需要写少量工具类。


posted @ 2006-09-20 09:02 Alex 阅读(923) | 评论 (1)编辑 收藏

注:关于跨域登陆cookie的问题在网上搜索了一下,没看到有java下的示例,这个asp的也可以参照一下,有空再在java下测一下.

key words:单点登陆 SSO 跨域cookie


摘要:当你有一个Cookie组(或叫Cookie字典)使用Domain属性指定域名之后,当你在对该组的成员进行修改或新增的时候,一定要在操 作之后加上Resonse.Cookies(CookieName).Domain属性。如果没有必要,请不要修改已设置Domain的Cookie组.
关键字:
正文:
    Cookie跨域操作看来是个简单的问题,因为只要指定Domain属性为指定网站的根域名就可以了.但是笔者在实际使用过程中却遇到了一些问题,的确值得注意.    环境介绍   cookie在www主域名下创建,并写入Domain属性,如:(为方便调试以下代码皆为asp代码)   Write.asp <%
Response.Cookies(CookieName)("UserName") = "SunBird"
Response.Cookies(CookieName)("Password") = "xyz1234"
Response.Cookies(CookieName).Domain = "xxxx.com"
%>
  上面文件放在www主域名下,同时在同目录下放置一个读取cookie的Read.asp   Read.asp <%
Response.Write Request.Cookies(CookieName)("UserName")
Response.Write Request.Cookies(CookieName)("Password")
%>
  再放一个Read.asp文件到另外一个子域名站点里,代码同上。最后我们再做一个清除cookie的Clear.asp放在主域名下   Clear.asp <%
Response.Cookies(CookieName)("UserName") = ""
Response.Cookies(CookieName)("Password") = ""
Response.Cookies(CookieName).Domain = "xxxx.com"
%>
  现在可以通过下面的执行顺序来测试,Write.asp-->主域名的Read.asp-->子域名的Read.asp 所有 Read.asp页面都可以读取到Write.asp创建的cookie的值,然后再运行Clear.asp进行清除,一切都Ok,看上去没有什么问题。   但是把这种方法运用到实际的站点时却出现问题了。   问题描述:   第一次登录一切ok,所有子域名都可以访问到主域名存储的cookie,但是,一旦退出之后,子域名的cookie被清除了,但是主域名的 cookie仍然保留着,强行清除主域名的cookie之后,无论怎样登录主域名下都无法保存cookie了,除非关掉浏览器重新打开。   经过多次尝试之后,无意中发现问题所在,以下是测试经过。   创建一个Write2.asp的页面放在主域名下 <%
Response.Cookies(CookieName)("TEST_COOKIE") = "TEST_COOKIE"
%>
  第一步:关闭浏览器后,按以下顺序执行,Write.asp-->主域名的Read.asp-->子域名的Read.asp 到这里所有Read.asp读取正常。   第二步:Clear.asp-->主域名的Read.asp-->子域名的Read.asp 到这里清除操作是成功的。   第三步:Write.asp--> Write2.asp --> 主域名Read.asp --> 子域名Read.asp 到这里两个Read.asp都可以读取到cookie的值。   第四步:重新执行第二步,发现主域名Read.asp仍然输出了值,而子域名下的Read.asp的值已经被清空了。   根据以上测试总结以下几点再跨域使用cookie时需要注意的地方   1、当你有一个Cookie组(或叫Cookie字典)使用Domain属性指定域名之后,当你在对该组的成员进行修改或新增的时候,一定要在操作之后加上Resonse.Cookies(CookieName).Domain属性。   2、如果没有必要,请不要修改已设置Domain的Cookie组,直接使用Response.Cookies("CookieText") = CookieValue 来创建一个新的Cookie。
posted @ 2006-09-18 20:59 Alex 阅读(2464) | 评论 (0)编辑 收藏

仅列出标题
共15页: First 上一页 2 3 4 5 6 7 8 9 10 下一页 Last