方寸心间

一路走,十年不回头

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  256 随笔 :: 9 文章 :: 38 评论 :: 3 引用

2009年8月17日 #

原理:

    我们先把树按照水平方式摆开。从根节点开始(“Food”),然后他的左边写上1。然后按照树的顺序(从上到下)给“Fruit”的左边写上2。这样,你沿着树的边界走啊走(这就是“遍历”),然后同时在每个节点的左边和右边写上数字。最后,我们回到了根节点“Food”在右边写上18。下面是标上了数字的树,同时把遍历的顺序用箭头标出来了。

 

    我们称这些数字为左值和右值(如,“Food”的左值是1,右值是18)。正如你所见,这些数字按时了每个节点之间的关系。因为“Red”有3和6两个值,所以,它是有拥有1-18值的“Food”节点的后续。同样的,我们可以推断所有左值大于2并且右值小于11的节点,都是有2-11的“Fruit” 节点的后续。这样,树的结构就通过左值和右值储存下来了。这种数遍整棵树算节点的方法叫做“改进前序遍历树”算法。

表结构设计:

 

常用的操作:

下面列出一些常用操作的SQL语句

返回完整的树(Retrieving a Full Tree)

SELECT node.name
  FROM nested_category node, nested_category parent
 WHERE node.lft BETWEEN parent.lft AND parent.rgt
   AND parent.name 'electronics'
 ORDER BY node.lft


返回某结点的子树(Find the Immediate Subordinates of a Node)

SELECT V.*
  FROM (SELECT node.name,
               (COUNT(parent.name) (AVG(sub_tree.depth) 1)) depth
          FROM nested_category node,
               nested_category parent,
               nested_category sub_parent,
               (SELECT V.*
                  FROM (SELECT node.name, (COUNT(parent.name) 1depth
                          FROM nested_category node, nested_category parent
                         WHERE node.lft BETWEEN parent.lft AND parent.rgt
                           AND node.name 'portable electronics'
                         GROUP BY node.name) V,
                       nested_category T
                 WHERE V.name T.name
                 ORDER BY T.lft) sub_tree
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
           AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
           AND sub_parent.name sub_tree.name
         GROUP BY node.name) V,
       nested_category T
 WHERE V.name T.name
   and V.depth <= 1
   and V.depth 0
 ORDER BY T.Lft


返回某结点的祖谱路径(Retrieving a Single Path)

SELECT parent.name
  FROM nested_category node, nested_category parent
 WHERE node.lft BETWEEN parent.lft AND parent.rgt
   AND node.name 'flash'
 ORDER BY node.lft


返回所有节点的深度(Finding the Depth of the Nodes)

SELECT V.*
  FROM (SELECT node.name, (COUNT(parent.name) 1depth
          FROM nested_category node, nested_category parent
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
         GROUP BY node.name) V,
       nested_category T
 WHERE V.name T.name
 ORDER BY T.Lft


返回子树的深度(Depth of a Sub-Tree)

SELECT V.*
  FROM (SELECT node.name,
               (COUNT(parent.name) (AVG(sub_tree.depth) 1)) depth
          FROM nested_category node,
               nested_category parent,
               nested_category sub_parent,
               (SELECT V.*
                  FROM (SELECT node.name, (COUNT(parent.name) 1depth
                          FROM nested_category node, nested_category parent
                         WHERE node.lft BETWEEN parent.lft AND parent.rgt
                           AND node.name 'portable electronics'
                         GROUP BY node.name) V,
                       nested_category T
                 WHERE V.name T.name
                 ORDER BY T.lft) sub_tree
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
           AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
           AND sub_parent.name sub_tree.name
         GROUP BY node.name) V,
       nested_category T
 WHERE V.name T.name
 ORDER BY T.Lft


返回所有的叶子节点(Finding all the Leaf Nodes)

SELECT name FROM nested_category WHERE rgt lft 1


插入节点(Adding New Nodes)

LOCK TABLE nested_category WRITE;

SELECT @myRight := rgt FROM nested_category WHERE name 'TELEVISIONS';

UPDATE nested_category SET rgt rgt 2 WHERE rgt @myRight;
UPDATE nested_category SET lft lft 2 WHERE lft @myRight;

INSERT INTO nested_category
  (name, lft, rgt)
VALUES
  ('GAME CONSOLES', @myRight 1@myRight 2);

UNLOCK TABLES;


删除节点(Deleting Nodes)

LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt lft 1
  FROM nested_category
 WHERE name 'GAME CONSOLES';

DELETE FROM nested_category WHERE lft BETWEEN @myLeft AND @myRight;

UPDATE nested_category SET rgt rgt @myWidth WHERE rgt @myRight;
UPDATE nested_category SET lft lft @myWidth WHERE lft @myRight;

UNLOCK TABLES;

posted @ 2009-08-17 09:51 方寸心间 阅读(996) 评论(0) 编辑

2009年7月9日 #

 

1.官方介绍的地址:

http://struts.apache.org/2.1.6/docs/convention-plugin.html


2.struts.xml文件配置

只挑选几个重要的常量说明:

(1) <constant name="struts.locale" value="zh_CN"/>
      <constant name="struts.i18n.encoding" value="UTF-8"/>

      struts2.1.6  现在只需要一个struts.xml文件就可以了。以前配struts.locale=zh_CN,struts.i18n.encoding=UTF-8,应用起动时会报一个警告,说没有配置locale,必须要在struts.properties里面配置才不会报错,现在这个问题已经解决了,所有配置都可以在xml文件中指定了。


(2) <constant name="struts.action.extension" value="action,do,,"/>

      扩展名可以指定为空。这样地址栏比较好看。但也会有个问题,就是一些其他servlet映射,如cxf,我们会映射地址为/services/*,现在这个地址也变成struts2控制范围的地址了,如果按默认的配置会报找不到action的错误。解决办法是修改mapper类。这在以后文章中会提到。


(3)  <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
       <constant name="struts.enable.SlashesInActionNames" value="true"/>

      开启动态方法。要实现零配置,就是需要动态方法调用。开启action名称可以有 “/”,一个请求地址有多个“/”,struts2就不会再使用类路径扫描的命名空间,只会使用配置的名称。所以既想action名称里使用“/”,又想用struts2默认搜索的命名空间,只能自己修改一下convention插件的实现类了。


(4) <constant name="struts.ui.theme" value="simple"/>

      不用dojo的及struts2复杂标签样式的就把主题设置为simple,这样可以不加载多余的模板。


(5) <constant name="struts.devMode" value="true"/>
      <constant name="struts.i18n.reload" value="true"/>
      <constant name="struts.configuration.xml.reload" value="true"/>
      <constant name="struts.convention.classes.reload" value="true" />

       开启开发者模式,在平时开发时修改action的annotation配置可以不重启,但是修改struts.xml文件还是要重启。修改类的具体内容,debug模式下可以不重启,或是使用javarebel,这个不在讨论范围。


(6)  <constant name="struts.convention.result.path" value="/WEB-INF/pages/"/>

      指定结果页面路径。 convention插件会自动在此路径中寻找文件。放到WEB-INF的目的的保护文件资源,只能通过程序内部跳转才能访问,我们的权限拦截器或其他权限处理只要加到action上就可以了。


(7) <constant name="struts.convention.action.suffix" value="Action"/>
     <constant name="struts.convention.action.name.lowercase" value="true"/>
     <constant name="struts.convention.action.name.separator" value="_"/>

     一个action名字的获取。比如为HelloWorldAction。按照配置,actionName为hello_world。


(8)<constant name="struts.convention.action.disableScanning" value="false"/>

     是否不扫描类。一定要设为false,否则convention插件不起作用,零配置也没有意义。


(9)<constant name="struts.convention.default.parent.package" value="default"/>

     设置默认的父包,一般我们都设置一个default包继承自struts-default。大部分类再继承default。如果有特殊的类需要特殊的包,只能在action中再指定父包了。


(10) <constant name="struts.convention.package.locators" value="action"/>
       <constant name="struts.convention.package.locators.disable" value="false"/>
       <constant name="struts.convention.package.locators.basePackage" value=""/>

   确定搜索包的路径。只要是结尾为action的包都要搜索。basePackage按照默认不用配置,如果配置,只会找以此配置开头的包。locators及locators.basePackage都是一组以逗号分割的字符串。


(11)  <constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate."/>

   排除哪些包不搜索。按默认配置即可。逗号分割字符串。


(12)  <constant name="struts.convention.action.includeJars" value="" />

   包括哪些jar包中的action。逗号分割字符串。


(13)<constant name="struts.convention.relative.result.types" value="dispatcher,freemarker,velocity"/>

   默认返回的结果类型搜索。按顺序先找相关的dispatcher的jsp文件是否存在。然后再找freemarker,再找velocity。


(14)<constant name="struts.convention.result.flatLayout" value="true"/>

      如果此值设为true,如果一个action的命名空间为/login,名称为HelloWorldAction。result返回值是success,默认会找到/WEB-INF/pages/login/hello_world.jsp(如果有hello_world_success.jsp就找这个文件,连接符“_”是在<constant name="struts.convention.action.name.separator" value="_"/>中配置的)。如果有一个action的result返回值是“error”,就会找/WEB-INF/pages /login/hello_world_error.jsp。

      如果此值设为false,如果一个action的命名空间为/login,名称为HelloWorldAction。result返回值是success,默认会找到/WEB- INF/pages/login/hello_world/index.jsp(如果有success.jsp就找这个文件)。如果有一个action的result返回值是“error”,就会找/WEB-INF/pages /login/hello_world/error.jsp。


(15) <constant name="struts.convention.action.mapAllMatches" value="false"/>
       <constant name="struts.convention.action.checkImplementsAction" value="false"/>
    <constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
    <constant name="struts.convention.redirect.to.slash" value="true"/>

      这几个配置没有太多的实际意义,本着最小检查的原则就可以。


(16)默认拦截器配置,已经简化了许多,一般不需要chain和 fileupload。modelDriven也没什么用,如果我们要使用restfull插件会有用。其实最简单只要一个params就可以了。我加入 exception是为了开发时的异常。servletConfig是为了包装一下request,reponse等对象,staticParams是为了可以配置${}形式参数。actionMappingParams是struts2.1新增的,我初步认为是可以在action配置中传参数,这个还有些疑问。


Xml代码
  1. <package name="default" extends="struts-default">     
  2.    <interceptors>     
  3.         <interceptor-stack name="defaultStack">     
  4.             <interceptor-ref name="exception" />     
  5.             <interceptor-ref name="servletConfig"/>     
  6.             <interceptor-ref name="actionMappingParams"/>     
  7.             <interceptor-ref name="staticParams"/>     
  8.             <interceptor-ref name="params" />     
  9.         </interceptor-stack>     
  10.     </interceptors>     
  11. </package>    

 

三.

1.Convention插件的主要实现浅析

1.1  PackageBasedActionConfigBuilder 这个类最重要,是整个程序的入口。
     1.1.1  buildActionConfigs方法进行初始化配置,其中findActions扫描类路径,我没有深入研究这个方法具体是怎么找到所有类的。只是找到全部类后,和我们的配置文件中限定的范围匹配、过滤,存入一个set中。然后buildConfiguration(set)循环分析这些类。

     1.1.2  buildConfiguration方法,首先创建一个map类型的packageConfigs。键为包(struts2)名,值为PackageConfig.Builder对象,这个对象可以创建PackageConfig对象。
      然后循环找到的类,分析包名(java),determineActionNamespace方法分析命名空间,得到一个list对象。
      再循环所有命名空间,determineActionName方法分析类名称、类的默认方法(这个是写死在程序中的,就是execute方法)。
      getPackageConfig方法分析得到PackageConfig.Builder对象。
      getActionAnnotations方法分析得到action类方法的annotation配置。
      循环每个方法的配置,调用createActionConfig方法分析,把results,interceptors,exceptionMappings等配置放入ActionConfig.Builder对象,再把ActionConfig对象(由ActionConfig.Builder生成)放入PackageConfig.Builder中。
      buildIndexActions创建默认索引action。这个好像用处不大。
      最后把PackageConfig对象放入Configuration对象中,这是最顶级的配置。我们在任何时间和地点都可以得到Configuration对象,并对其进行分析。

     1.1.3   determineActionNamespace方法是确定一个action类在web应用中的命名空间,先找这个类的Namespace注解,找到后放入一个存储命名空间的list。再找Namespaces注解,一个action可以有多个命名空间。如果有注解则按照注解来确定一个action的命名空间,如果没有,则分析这个action所在包(java)的路径,按照struts2.xml中配置的规则来确定。这个规则就是截取到定义的locator,在这个locator之后的包(java)全部作为命名空间,类名作为action名称。

     1.1.4   determineActionName方法是确定一个action类在web应用中的名称。由ActionNameBuilder(接口)的方法来实现,这个接口的具体实现类,插件默认为SEOActionNameBuilder。被称为搜索引擎友好的名称。会把action类的name按单词分解,然后用连接符连起来。默认连接符是"-",我们可以设置为"_"。

     1.1.5   getPackageConfig方法是确定一个action类在web应用中的继承的包(struts2)。先找这个类的ParentPackage注解,如果有注解则按照注解来确定一个action的父包(struts2),如果没有,按照struts.xml中配置的规则来确定。这个规则就是defaultParentPackage。得到父包(struts2)后要拼成: actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace 的形式,这是xwork里的规定。

     1.1.6   getActionAnnotations方法是确定一个action类的方法上的annotation配置。先找方法的Actions注解,一个方法可以有多个action映射。再找Action注解,放入一个map中,键是方法名,值是存储一组acton映射的list对象。
    
      1.1.7   createActionConfig方法构造ActionConfig.Builder对象,逐一判断interceptors,results,exceptionMappings,都是从类一级开始判断是否有此注解,再从方法的action注解中寻找。InterceptorMapBuilder,ResultMapBuilder是两个接口,提供通过注解构造Interceptor和Result的方法,插件分别提供了默认的实现DefaultInterceptorMapBuilder和DefaultResultMapBuilder。而buildExceptionMappings只是本类中的一个方法。

1.2  DefaultInterceptorMapBuilder
     先找action类是否存在InterceptorRefs注解,再看是否存在InterceptorRef注解,再看action注解中是否定义了InterceptorRefs。
     还用到了StringTools的createParameterMap方法把注解中的params(形式为{key1,value1,key2,value2,......})转化成一个map。
      buildInterceptorList方法利用了xwork中的InterceptorBuilder的一个静态方法constructInterceptorReference把拦截器注入到配置中。
      而一个action所继承的父包中的拦截器,或是默认拦截器,并不在这个类中构造。而是由xwork根据包(struts2)的继承关系加载(actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace 这是xwork里规定的形式,已经由PackageBasedActionConfigBuilder 配置)。

1.3 DefaultResultMapBuilder
    1.3.1  build方法,确定defaultResultPath,构造包含ResultConfig的map对象,再通过扩展名获得一个包含ResultTypeConfig的map对象。createFromResources方法获得默认返回结果页面,然后查找action注解中的results配置,再找类级别的Results注解,再找类级别的Result注解,相同的肯定会覆盖。createFromAnnotations。

    1.3.2  createFromResources方法中使用servletContext.getResourcePaths方法寻找页面。如果struts.xml中配置flatLayout为true则直接找到以命名空间为名称的文件夹,在此文件夹中寻找页面,如果flatLayout为false,则会找到以命名空间为名称的文件夹,再找到此文件夹中的以action名称命名的子文件夹,在这个文件夹中寻找页面。

    1.3.3  makeResults方法找默认的返回页面,如果没有路径没有包含resultcode(定义的字符串)的页面,则按默认顺序寻找success,input,error。比如hello_world.jsp文件(flatLayout为true,连接符为"_"),如果没有hello_world_success.jsp,hello_world_input.jsp,hello_world_error.jsp文件,同时"success","input","error",又没有显式的配置,只是作为结果字符串返回,则程序默认会用hello_world.jsp来匹配三种结果。如果结果字符串resultcode是"edit",同时又没有显式的配置,则必会找hello_world_edit.jsp。

    1.3.4  createFromAnnotations这个方法就是把注解转换成ResultConfig配置。

1.4 ConventionsServiceImpl
    是result配置的辅助类。determineResultPath方法先判断struts.xml文件中的配置,再判断action类的注解中是否有ResultPath,如果有将覆盖struts.xml中配置。
     getResultTypesByExtension方法提供一个map对象,默认的result结果返回。

      其实通过看这些方法,我们也基本了解了struts2的整个配置过程,非常繁琐,很多的判断确实很耗费资源,使用xml配置也一样。我们也知道所有配置信息都是应用启动时加载,存入map中常驻内存。所以我们应该尽可能减少配置,多使用动态方法调用。

1.5  ConventionUnknownHandler 是UnknownHandler接口的一个实现,用来处理找不到相应配置的情况。在struts2.1的dtd中新增了一个<unknown-handler-stack>元素,可以配置一组handler。
       handleUnknownAction方法处理找不到action的情况。这个我感觉用处不大。
       handleUnknownResult方法处理找不到result的情况。这个方法可以有很多扩展。比如我想定义一种返回值形式:redirect->xxx.do?ad=12或chain->xxx.do。用这种形式比写注解要方便的多。
       handleUnknownActionMethod方法处理找不到action中方法的情况。这个默认没有实现。


 

posted @ 2009-07-09 12:04 方寸心间 阅读(311) 评论(0) 编辑

2008年12月17日 #

public class SortAll {   
  
 
/**  
  * 冒泡排序,选择排序,插入排序,希尔(Shell)排序 Java的实现   
  * 2008.11.09  
  * 
@author YangL. (http://www.idcn.org)  
  
*/  
 
public static void main(String[] args) {   
  
int[] i = { 15612493233940359687 };   
  System.out.println(
"----冒泡排序的结果:");   
  maoPao(i);   
  System.out.println();   
  System.out.println(
"----选择排序的结果:");   
  xuanZe(i);   
  System.out.println();   
  System.out.println(
"----插入排序的结果:");   
  chaRu(i);   
  System.out.println();   
  System.out.println(
"----希尔(Shell)排序的结果:");   
  shell(i);   
 }   
  
 
// 冒泡排序   
 public static void maoPao(int[] x) {   
  
for (int i = 0; i < x.length; i++) {   
   
for (int j = i + 1; j < x.length; j++) {   
    
if (x[i] > x[j]) {   
     
int temp = x[i];   
     x[i] 
= x[j];   
     x[j] 
= temp;   
    }   
   }   
  }   
  
for (int i : x) {   
   System.out.print(i 
+ " ");   
  }   
 }   
  
 
// 选择排序   
 public static void xuanZe(int[] x) {   
  
for (int i = 0; i < x.length; i++) {   
   
int lowerIndex = i;   
   
// 找出最小的一个索引   
   for (int j = i + 1; j < x.length; j++) {   
    
if (x[j] < x[lowerIndex]) {   
     lowerIndex 
= j;   
    }   
   }   
   
// 交换   
   int temp = x[i];   
   x[i] 
= x[lowerIndex];   
   x[lowerIndex] 
= temp;   
  }   
  
for (int i : x) {   
   System.out.print(i 
+ " ");   
  }   
 }   
  
 
// 插入排序   
 public static void chaRu(int[] x) {   
  
for (int i = 1; i < x.length; i++) {// i从一开始,因为第一个数已经是排好序的啦   
   for (int j = i; j > 0; j--) {   
    
if (x[j] < x[j - 1]) {   
     
int temp = x[j];   
     x[j] 
= x[j - 1];   
     x[j 
- 1= temp;   
    }   
   }   
  }   
  
for (int i : x) {   
   System.out.print(i 
+ " ");   
  }   
 }   
  
 
// 希尔排序   
 public static void shell(int[] x) {   
  
// 分组   
  for (int increment = x.length / 2; increment > 0; increment /= 2) {   
   
// 每个组内排序   
   for (int i = increment; i < x.length; i++) {   
    
int temp = x[i];   
    
int j = 0;   
    
for (j = i; j >= increment; j -= increment) {   
     
if (temp < x[j - increment]) {   
      x[j] 
= x[j - increment];   
     } 
else {   
      
break;   
     }   
    }   
    x[j] 
= temp;   
   }   
  }   
  
  
for (int i : x) {   
   System.out.print(i 
+ " ");   
  }   
 }   
}  
posted @ 2008-12-17 17:35 方寸心间 阅读(1874) 评论(0) 编辑

2008年12月12日 #

准备:
1.apache-ant-1.7.0.
2.hibernate-3.2.1.ga.zip,HibernateTools-3.2.1.ga.zip.
3.数据库的jdbc驱动程序,我使用的是mysql,驱动程序为mysql-connector-java-5.1.6。

项目布置:
1.建立Project-Name文件夹,其下建立:config,java,schema,lib文件夹以及build.xml文件.
2.加入jar包:hibernate3.jar,hibernate-tools.jar,freemarker.jar,mysql-connector-java.jar,...
3.src/hibernate.cfg.xml:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>

<hibernate-configuration>
 
<session-factory>
  
<property name="connection.username">root</property>
  
<property name="connection.password">cosmo</property><!--Your DB password here.-->
  
<property name="connection.url">jdbc:mysql://localhost:3306/MasteryHibernate</property>
  
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
  
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  
<mapping resource="chapter3/Customer.hbm.xml" />
 
</session-factory>
</hibernate-configuration>

4.src/your-package/Customer.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

<hibernate-mapping>
    
<class name="chapter3.Customer" table="CUSTOMERS">
        
<meta attribute="class-description">
            Represents a single customer.
            @author Cosmo
        
</meta>

        
<meta attribute="class-scope">public</meta>

        
<id name="id" type="long" column="ID">
            
<meta attribute="scope-set">protected</meta>
            
<generator class="native" />
        
</id>

        
<property name="name" type="string">
            
<meta attribute="use-in-tostring">true</meta>
            
<column name="NAME" length="15" not-null="true" unique="true" />
        
</property>

        
<property name="registeredTime" type="timestamp">
            
<meta attribute="field-description">When the customer was registered</meta>
            
<meta attribute="use-in-tostring">true</meta>
            
<column name="REGISTERED_TIME" index="IDX_REGISTERED_TIME"
                sql-type
="timestamp" />
        
</property>
        
        
<property name="age" type="int">
            
<meta attribute="field-description">How old is the customer</meta>
            
<meta attribute="use-in-tostring">true</meta>
            
<column name="AGE" check="AGE>10" not-null="true" />
        
</property>
        
        
<property name="sex" type="char" column="SEX" />
        
        
<property name="married" type="boolean" column="IS_MARRIED">
            
<meta attribute="field-description">Is the customer married</meta>
            
<meta attribute="use-in-tostring">true</meta>
        
</property>
        
        
<property name="description" type="string">
            
<meta attribute="use-in-tostring">true</meta>
            
<column name="DESCRIPTION" sql-type="text" />
        
</property>
    
</class>
</hibernate-mapping>

5.build.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!-- ====================================================================== 
     2008-12-12 下午02:47:47                                                        

     Hbm2javaAndHbm2ddl    
     Useing hibernate-tools
                   
     Cosmo                                                                
     ====================================================================== 
-->
<project name="AboutHibernateTools" default="compile">
    
<description>
            AboutHibernateTools
    
</description>

    
<property name="source.root" value="./src" />
    
<property name="class.root" value="./classes" />
    
<property name="lib.dir" value="./lib" />
    
<property name="schema.dir" value="./schema" />

    
<path id="project.class.path">
        
<pathelement location="${class.root}" />
        
<fileset dir="${lib.dir}">
            
<include name="*.jar" />
        
</fileset>
    
</path>

    
<!-- ================================= 
          target: run              
         ================================= 
-->
    
<target name="run" depends="hbm2ddl" description="Run a Hibernate sample">
        
<java classname="chapter3.BusinessService" fork="true">
            
<classpath refid="project.class.path" />
        
</java>
    
</target>


    
<!-- ================================= 
          target: hbm2ddl              
         ================================= 
-->
    
<target name="hbm2ddl" depends="compile" description="Generate DB schema from the O/R mapping files">
        
<mkdir dir="${schema.dir}" />
        
<taskdef name="hbm2ddl" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="project.class.path" />
        
<hbm2ddl destdir="${schema.dir}">
            
<configuration configurationfile="${class.root}/hibernate.cfg.xml" />
            
<hbm2ddl export="true" console="false" create="true" update="false" drop="false" outputfilename="schema.sql" />
        
</hbm2ddl>
    
</target>


    
<!-- ================================= 
          target: compile              
         ================================= 
-->
    
<target name="compile" depends="hbm2java" description="Chapter3">
        
<javac srcdir="${source.root}" destdir="${class.root}" debug="on" optimize="off" deprecation="on">
            
<classpath refid="project.class.path" />
        
</javac>
    
</target>

    
<!-- ================================= 
          target: hbm2java              
         ================================= 
-->
    
<target name="hbm2java" depends="prepare" description="Generate Java source from the O/R mapping files">
        
<taskdef name="hbm2java" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="project.class.path" />
        
<hbm2java destdir="${source.root}">
            
<configuration configurationfile="${class.root}/hibernate.cfg.xml" />
            
<hbm2java jdk5="true" />
        
</hbm2java>
    
</target>


    
<!-- - - - - - - - - - - - - - - - - - 
          target: prepare                      
         - - - - - - - - - - - - - - - - - 
-->
    
<target name="prepare">
        
<delete dir="${class.root}" />
        
<mkdir dir="${class.root}" />

        
<copy todir="${class.root}">
            
<fileset dir="${source.root}">
                
<include name="**/*.properties" />
                
<include name="**/*.hbm.xml" />
                
<include name="**/*.cfg.xml" />
            
</fileset>
        
</copy>
    
</target>

</project>


 

posted @ 2008-12-12 16:33 方寸心间 阅读(531) 评论(0) 编辑

2008年11月23日 #

unsaved-value是表示一个对象是新的还是旧的,当显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value的。某些情况下(父子表关联保存),当你在程序中并没有显式的使用save或者update一个持久对象,那么Hibernate需要判断被操作的对象究竟是一个已经持久化过的持久对象,是一个尚未被持久化过的内存临时对象。例如:

CODE:    
Session session 
= ;    
Transaction tx 
= ;    
Parent parent 
= (Parent) session.load(Parent.class, id);    
Child child 
= new Child();    
child.setParent(parent);    
child.setName(
"sun");    
parent.addChild(child);    
s.update(parent);    
s.flush();    
tx.commit();    
s.close();

 

在上例中,程序并没有显式的session.save(child); 那么Hibernate需要知道child究竟是一个临时对象,还是已经在数据库中有的持久对象。如果child是一个新创建的临时对象(本例中就是这种情况),那么Hibernate应该自动产生session.save(child)这样的操作,如果child是已经在数据库中有的持久对象,那么Hibernate应该自动产生session.update(child)这样的操作。3^)N%Q(}z1U        Q$x
因此我们需要暗示一下Hibernate,究竟child对象应该对它自动save还是update。在上例中,显然我们应该暗示Hibernate对child自动save,而不是自动update。那么Hibernate如何判断究竟对child是save还是update呢?它会取一下child的主键属性 child.getId() ,这里假设id是 java.lang.Integer类型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate认为child是新的内存临时对象,发送save,如果不相等,那么Hibernate认为child是已经持久过的对象,发送update。`_/Zw
mV-yWr

unsaved-value="null" (默认情况,适用于大多数对象类型主键 Integer/Long/String/...)
当Hibernate取一下child的Id,取出来的是null(在上例中肯定取出来的是null),和unsaved-value设定值相等,发送save(child)
当Hibernate取一下child的id,取出来的不是null,那么和unsaved-value设定值不相等,发送update(child)
例如下面的情况:

CODE:    
Session session 
= ;    
Transaction tx 
= ;    
Parent parent 
= (Parent) session.load(Parent.class, id);    
Child child 
= (Child) session.load(Child.class, childId);    
child.setParent(parent);    
child.setName(
"sun");    
parent.addChild(child);    
s.update(parent);    
s.flush();    
tx.commit();    
s.close();


child已经在数据库中有了,是一个持久化的对象,不是新创建的,因此我们希望Hibernate发送update(child),在该例中,Hibernate取一下child.getId(),和unsave-value指定的null比对一下,发现不相等,那么发送update(child)。
BTW: parent对象不需要操心,因为程序显式的对parent有load操作和update的操作,不需要Hibernate自己来判断究竟是save还是update了。我们要注意的只是child对象的操作。另外unsaved-value是定义在Child类的主键属性中的。

CODE:    
<class name="Child" table="child">    
"id" name="id" type="integer" unsaved-value="null">    
  class="identity"/>    
   
    
class>

如果主键属性不是对象型,而是基本类型,如int/long/double/...,那么你需要指定一个数值型的unsaved-value
例如:

CODE:
unsaved-null="0"


在此提醒大家,很多人以为对主键属性定义为int/long,比定义为Integer/Long运行效率来得高,认为基本类型不需要进行对象的封装和解构操作,因此喜欢把主键定义为int/long的。但实际上,Hibernate内部总是把主键转换为对象型进行操作的,就算你定义为int/long型的,Hibernate内部也要进行一次对象构造操作,返回给你的时候,还要进行解构操作,效率可能反而低也说不定。因此大家一定要扭转一个观点,在Hibernate中,主键属性定义为基本类型,并不能够比定义为对象型效率来的高,而且也多了很多麻烦,因此建议大家使用对象型的Integer/Long定义主键。
unsaved-value="none"和 悠忆社区/V,tq9fs
unsaved-value="any"
主要用在主键属性不是通过Hibernate生成,而是程序自己setId()的时候。www.yoy1.com#m4iCO'n\$T
在这里多说一句,强烈建议使用Hibernate的id generator,或者你可以自己扩展Hibernate的id generator,特别注意不要使用有实际含义的字段当做主键来用!例如用户类User,很多人喜欢用用户登陆名称做为主键,这是一个很不好的习惯,当用户类和其他实体类有关联关系的时候,万一你需要修改用户登陆名称,一改就需要改好几张表中的数据。偶合性太高,而如果你使用无业务意义的id generator,那么修改用户名称,就只修改user表就行了。
由这个问题引申出来,如果你严格按照这个原则来设计数据库,那么你基本上是用不到手工来setId()的,你用Hibernate的id generator就OK了。因此你也不需要了解当社会,体育,生活,情感,搞笑,JAVA技术交流,软件交流,IT资讯(r9j.@%u:s@4k_7P,P
unsaved-value="none"和 社会,体育,生活,情感,搞笑,JAVA,struts,hibernate技术交流,软件交流,IT资讯t;P|_0R+vy,g)z6H
unsaved-value="any"社会,体育,生活,情感,搞笑,JAVA技术交流,软件交流,IT资讯7W'N0W9W'R\
究竟有什么含义了。如果你非要用assigned不可,那么继续解释一下:b i9d e1W[B
unsaved-value="none" 的时候,由于不论主键属性为任何值,都不可能为none,因此Hibernate总是对child对象发送update(child)社会,体育,生活,情感,搞笑,JAVA,struts,hibernate技术交流,软件交流,IT资讯 C5pm
x.o:o

unsaved-value="any" 的时候,由于不论主键属性为任何值,都肯定为any,因此Hibernate总是对child对象发送save(child)社会,体育,生活,情感,搞笑,JAVA技术交流,软件交流,IT资讯G.H#n&WK6WZYWB
大多数情况下,你可以避免使用assigned,只有当你使用复合主键的时候不得不手工setId(),这时候需要你自己考虑究竟怎么设置unsaved-value了,根据你自己的需要来定。
强烈不建议使用composite-id,强烈建议使用UserType。
因此,如果你在系统设计的时候,遵循如下原则:Y?GS*w
OKYw

1、使用Hibernate的id generator来生成无业务意义的主键,不使用有业务含义的字段做主键,不使用assigned。社会,体育,生活,情感,搞笑,JAVA,struts,hibernate技术交流,软件交流,IT资讯:EOs7Z$P"`6h
2、使用对象类型(String/Integer/Long/...)来做主键,而不使用基础类型(int/long/...)做主键社会,体育,生活,情感,搞笑,JAVA,struts,hibernate技术交流,软件交流,IT资讯\MJ%d\b
TI

3、不使用composite-id来处理复合主键的情况,而使用UserType来处理该种情况。
#yo9LLlU a
那么你永远用的是unsaved-value="null" ,不可能用到any/none/..了。

posted @ 2008-11-23 17:26 方寸心间 阅读(399) 评论(0) 编辑

2008年11月19日 #

摘要: 在使用InelliJ IDEA的过程中,通过查找资料以及一些自己的摸索,发现这个众多Java程序员喜欢的IDE里有许多值得一提的小窍门,如果能熟练的将它们应用于实际开发过程中,相信它会大大节省你的开发时间,而且随之而来的还会有那么一点点成就感:)Try it!1、写代码时用Alt-Insert(Code|Generate…)可以创建类里面任何字段的getter与setter方法。2、右...阅读全文
posted @ 2008-11-19 21:27 方寸心间 阅读(620) 评论(1) 编辑

2008年11月17日 #

摘要: maven2 起步 相信maven1 大家都已经很熟悉了,具体maven能做什么,就不详细说了。个人觉得maven在开源项目中用的还是比较多的,公司内部,就不太清楚了。我以前的公司用过一段时间,不过后来就没有下文了。 与maven1 相比,maven2可算是几乎重写了,不过从速度来说应该更快。 主要的几个新特性包括:(详细参考http://www.ibm.com/developerworks/cn...阅读全文
posted @ 2008-11-17 23:53 方寸心间 阅读(640) 评论(0) 编辑

2008年11月15日 #

摘要: HSQLDB 是一个轻量级的纯Java开发的开放源代码的关系数据库系统。因为HSQLDB的轻量(占用空间小),使用简单,支持内存运行方式等特点,HSQLDB被广泛用于开发环境和某些中小型系统中。HSQLDB的运行需要Java环境的支持。HSQLDB的四种运行模式: 运行模式 说明 启动命令 JDBC例 内存(Memory-Only)模式 所有数据都在内存里操作。应用程序退出后则数据被销毁。 启动方...阅读全文
posted @ 2008-11-15 09:22 方寸心间 阅读(2662) 评论(0) 编辑

2008年10月17日 #

摘要: response.setHeader 是用来设置返回页面的头 meta 信息, 使用时 response.setHeader( name, contect ); meta是用来在HTML文档中模拟HTTP协议的响应头报文。meta 标签用于网页的<head>与</head>中 1、<meta name="Generator" contect="">用以说明生成工...阅读全文
posted @ 2008-10-17 18:23 方寸心间 阅读(1759) 评论(0) 编辑

2008年10月15日 #

摘要: 一.下载proxool去proxool官网下载proxool,最新版本是0.9.1。下载完后解压,把proxool.jar和proxool-cglib.jar放入你要配置的项目的lib目录下.二.配置proxool.xml添加proxool.xml文件到项目的/WEB-INF下.连接数据库Oracle的配置如下:[代码]alias:数据源的别名driver-url:url连接串,须确定用户名和密码...阅读全文
posted @ 2008-10-15 12:23 方寸心间 阅读(6290) 评论(0) 编辑