卸载Oracle10g步骤
很郁闷的不知道为啥的装Oracle10g就出错了,无法创建实例等问题。于是就想到先卸载,但是之前听说Oracle的卸载异常麻烦,之前是用9i的,听过如果第一次装失败,基本上要重装系统了。不过今天百度了下,并且按照里面的做了,接着再装Oracle就可以了,于是记录下具体卸载方法:(摘自网上)
0、开始->设置->控制面板->添加删除程序-> Oracle Data Provider for .Net Help 1、开始->设置->控制面板->管理工具->服务停止所有Oracle服务; 2、开始->程序->Oracle – OraDb10g_home1>Oracle Installation Products-> Universal Installer 卸装所有Oracle产品,但Universal Installer本身不能被删除; 3、运行regedit,选择HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE,按del键删除这个入口; 4、运行regedit,选择HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,滚动这个列表,删除所有Oracle入口; 5、运行regedit,选择HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application,删除所有Oracle入口; 6、开始->设置->控制面板->系统->高级->环境变量,删除环境变量CLASSPATH和PATH中有关Oracle的设定; 7、从桌面上、STARTUP(启动)组、程序菜单中,删除所有有关Oracle的组和图标; 8、删除c:\Program Files\Oracle目录; 9、重新启动计算机,重起后才能完全删除Oracle所在目录 ; 10、删除与Oracle有关的文件,选择Oracle所在的缺省目录C:\Oracle,删除这个入口目录及所有子目录,并从Windows XP目录(一般为d:\WINDOWS)下删除以下文件ORACLE.INI、oradim73.INI、oradim80.INI、oraodbc.ini等等; 11、WIN.INI文件中若有[ORACLE]的标记段,删除该段; 12、如有必要,删除所有Oracle相关的ODBC的DSN(管理工具/数据源(ODBC)); 13、到事件查看器(管理工具/事件查看器)中,删除Oracle相关的日志(只能删除所有,右击某个目录,清除所有事件) |
其中有很多步我都没用到,可能是因为刚刚装完的缘故吧。还没产生其他垃圾数据和文件。
ExtJs2.3在IE6中出现"拖动无法停止"解决方法
刚开始接触Ext,下载了3.2的,结果又下载了2.3的,反正2.3的有教程,还是符合教程的平台吧。写了第一个很简单的程序如下:
<link rel="stylesheet" type="text/css" href="./extlib/resources/css/ext-all.css"> <script type="text/javascript" src="./extlib/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="./extlib/ext-all.js"></script> <script type="text/javascript" src="./extlib/build/locale/ext-lang-zh_CN.js"></script> <script type="text/javascript"> Ext.onReady(function(){ Ext.MessageBox.alert("提示框","欢迎进入EXT世界"); }); </script> </head> <body> This is my HTML page. <br> </body>
结果出现如下现象:
当拖动这个提示框的时候,会一直处于这种拖动状态,页面被锁住了,无法进行下一步操作,页面瘫痪了。而在FF下则显示正常。
现在如图:
谷歌得解:
解决方法:在<body>标签中需要加入<div>标签则可以解决问题。如:
<body> <div> This is my HTML page. <br> </div> </body>
SVN莫名奇妙的错误
就改了个路径,莫名奇妙的各种问题都出来了,什么锁定啊,树冲突啊,更新提示说没有更新的文件,提交显示目录不存在或者冲突之类的,实在很无语。后来想到了个猥琐的方法,如下:
把要提交的svn目录下,搜索出.svn文件,然后把这些文件干掉,再提交就可以了。
组合模式
总结关于组合模式的目的:
客户程序可以向处理简单元素一样来处理复杂元素。
关于组合模式的作用:
可用于处理对象的部分-整体结构,经常用于处理拥有树状结构的问题。
对应的类图:
下列贴一段代码来说明应用组合模式+迭代器来模拟对树的遍历,顺便复习了数据结构中的树相关知识。本代码参考网上相关代码:
/** * 结点接口 * @author ChenST */ public interface Node { /** * 添加结点 * @param node */ public void add(Node node); /** * 获取一个迭代器 * @return */ public Iterator<Node> iterator(); }
/** * 抽象结点,主要实现toString方法,可用于识别各个结点 * @author ChenST * */ public abstract class AbstractNode implements Node{ /** 结点名字 */ protected String nodeName; public AbstractNode(String nodeName){ this.nodeName = nodeName; } public String toString(){ return nodeName; } }
/** * 叶子结点,不允许有子结点 * @author ChenST */ public class LeafNode extends AbstractNode { public LeafNode(String nodeName) { super(nodeName); } @Override public void add(Node node) { throw new UnsupportedOperationException("叶子结点不能添加结点"); } @Override public Iterator<Node> iterator() { //返回空的迭代器,永远无法进行迭代 return new NullIterator<Node>(); } }
/** * 枝结点,可存储多数叶子结点 * @author ChenST */ public class BranchNode extends AbstractNode { //树枝结点下的所有孩子结点 private List<Node> childs = new ArrayList<Node>(); public BranchNode(String nodeName) { super(nodeName); } @Override public void add(Node node) { childs.add(node); } @Override public Iterator<Node> iterator() { return childs.iterator(); } }
/** * 空的迭代器 * @author ChenST * * @param <T> */ public class NullIterator<T> implements Iterator<T> { @Override public boolean hasNext() { //永远没有下一个结点 return false; } @Override public T next() { //永远为空 return null; } @Override public void remove() { //没有移除方法 } }
/** * 深度优先迭代器 * @author ChenST */ public class DepthFirstIterrator implements Iterator<Node> { //堆栈 private Stack<Iterator<Node>> stack = new Stack<Iterator<Node>>(); public DepthFirstIterrator(Iterator<Node> iter){ this.stack.push(iter); } @Override public boolean hasNext() { if(stack.isEmpty()){ return false; }else{ Iterator<Node> iter = this.stack.peek(); if(iter.hasNext()){ return true; }else{ this.stack.pop(); return hasNext(); } } } @Override public Node next() { if(hasNext()){ Iterator<Node> iter = this.stack.peek(); Node node = iter.next(); if(node instanceof BranchNode){ this.stack.push(node.iterator()); } return node; } return null; } @Override public void remove() { throw new UnsupportedOperationException("不支持移除操作"); } }
/** * 广度优先算法的迭代器 * @author ChenST */ public class BreadthFirstIterator implements Iterator<Node> { //存储临时结点操作的队列 private Queue<Iterator<Node>> queue = new LinkedList<Iterator<Node>>(); public BreadthFirstIterator(Iterator<Node> iter){ queue.offer(iter); } @Override public boolean hasNext() { if(queue.isEmpty()){ return false; }else{ Iterator<Node> iter = queue.peek(); if(iter.hasNext()){ return true; }else{ queue.poll(); return hasNext(); } } } @Override public Node next() { if (hasNext()) { Iterator<Node> it = queue.peek(); Node node = it.next(); if(node instanceof BranchNode){ queue.offer(node.iterator()); } return node; } return null; } @Override public void remove() { throw new UnsupportedOperationException("不支持移除操作"); } }
public class Test { public static void main(String[] args) { //构建树 Node A = new BranchNode("A"); Node B = new BranchNode("B"); Node C = new BranchNode("C"); Node D = new BranchNode("D"); Node E = new LeafNode("E"); Node F = new LeafNode("F"); Node G = new LeafNode("G"); Node K = new LeafNode("K"); A.add(B); A.add(C); B.add(D); B.add(E); C.add(F); D.add(G); D.add(K); //深度优先迭代器 System.out.print("深度优先迭代器:"+A); Iterator<Node> iterDepth = new DepthFirstIterrator(A.iterator()); while(iterDepth.hasNext()){ System.out.print(iterDepth.next()); } //广度优先迭代器 Iterator<Node> iterBreadth = new BreadthFirstIterator(A.iterator()); System.out.print("\n广度优先迭代器:"+A); while(iterBreadth.hasNext()){ System.out.print(iterBreadth.next()); } } }
深度优先迭代器:ABDGKECF 广度优先迭代器:ABCDEFGK
本例子利用自定义迭代器(深度优先迭代器和广度优先迭代器)对构建的树进行了访问。可以看到利用组合模式不管对叶子结点访问还是对整颗树进行访问或者对树的某个子树进行访问都是用同样的方法都可以达到目的。这就是组合模式的核心。
桥接模式
关于桥接模式的定义:
将抽象与行为相分离,使得他们各自可以独立变化,然后可通过动态组合得到想要的结果,目标是实现解耦。桥接模式的类关系图如下:
现在举一个例子来说明桥接模式.
以最常用的咖啡问题来说明。现在模拟的场景是这样子的:
咖啡有分大杯和中杯,同时咖啡里面可以选择加牛奶,也可以选择加苹果汁,也可以什么都不加。因为刚开张,所以目前就只有大杯和中杯,未来可能会有更多规格的杯子,同时也会有更多的调料给客人选择,设计一个具有弹性的程序 |
分析:按照目前的情况,最简单的做法就是分别写出6种类,来表示六种不同组合的咖啡。
我们可以分析到这种做法虽然和直观,但是会存在很多问题,其中之一就是这6个类的每一个类都已经具体的代表了一种咖啡,换句话说,这几个类是没办法复用的,这当然是我们不想要的,另外一个问题就是,如果添加一个规格的杯子,比如小杯,又要再写小杯中分别加不同调料的类,可想而知,后面店的规模大起来的话,会造成类的“炸弹”。
我们想要的结果是,当增加一种调料时只需要增加一个类,增加一个杯子规模的时候也只需要增加一个类就可以达到目的,这就需要用到桥接模式了。
桥接模式分析法:把属性和行为分别抽象并独立开来,行为就是加牛奶加苹果汁等,属性就是大杯中杯之类的。我们的目的就是把行为和属性完全没有耦合,通过组合来形成不同的咖啡,通俗点说,例如我们只提供的各种零件,让使用者去使用而已,不提供整合好的东西。
请看分析的类图:
具体来看看代码的实现:
/** * 咖啡的行为 * @author ChenST * */ public interface Action { /** * 做事情 * @return */ public String doThing(); }
/** * 加牛奶的行为 * @author ChenST */ public class AddMilkAction implements Action { @Override public String doThing() { return "加了[牛奶]"; } }
/** * 什么也不加的行为 * @author ChenST */ public class EmptyAction implements Action { @Override public String doThing() { return "什么也没加"; } }
/** * 加了苹果汁 * @author ChenST * */ public class AddAppleAction implements Action { @Override public String doThing() { return "加了[苹果汁]"; } }
/** * 咖啡抽象类 * @author ChenST */ public abstract class Coffee { private Action action; public Coffee(Action action){ this.action = action; System.out.println(this.result()); } public Action getAction(){ return action; } /** * 得到的咖啡结果 * @return */ public abstract String result(); }
/** * 大杯咖啡 * @author ChenST */ public class BigCupCoffe extends Coffee { public BigCupCoffe(Action action){ super(action); } @Override public String result() { String thing = this.getAction().doThing(); return "[大杯]"+thing+"的咖啡"; } }
/** * 中杯咖啡 * @author ChenST * */ public class MiddleCupCoffee extends Coffee { public MiddleCupCoffee(Action action){ super(action); } @Override public String result() { String thing = this.getAction().doThing(); return "[中杯]"+thing+"的咖啡"; } }
public class Test { public static void main(String[] args) { //加牛奶的大杯咖啡 Coffee coffee1 = new BigCupCoffe(new AddMilkAction()); //什么也没加的大杯咖啡 Coffee coffee2 = new BigCupCoffe(new EmptyAction()); //加苹果汁的大杯咖啡 Coffee coffee3 = new BigCupCoffe(new AddAppleAction()); //加牛奶的中杯咖啡 Coffee coffee4 = new MiddleCupCoffee(new AddMilkAction()); //什么也没加的中杯咖啡 Coffee coffee5 = new MiddleCupCoffee(new EmptyAction()); //加苹果汁的中杯咖啡 Coffee coffee6 = new MiddleCupCoffee(new AddAppleAction()); } }
[大杯]加了[牛奶]的咖啡 [大杯]什么也没加的咖啡 [大杯]加了[苹果汁]的咖啡 [中杯]加了[牛奶]的咖啡 [中杯]什么也没加的咖啡 [中杯]加了[苹果汁]的咖啡
代理模式-静态代理
相对于动态代理,静态代理好理解多了。
看静态代理涉及的角色以及相关关系图
再来看看代码实现,(相关知识写在代码注释中了~呵~)
//抽象对象 public interface ISubject { public void request(); }
//真实对象,实现类 public class SubjectImpl implements ISubject{ @Override public void request() { System.out.println("hello world"); } }
//代理对象 ,代理对象和实际对象都实现了抽象对象 //这样的好处,可以用代理对象来完成相应的操作, //也可以用实际对象来完成操作 //某些情况,就是不想通过实际对象去完成操作, //要交给代理对象去完成相应的操作. public class SubjectProxy implements ISubject { //组合真实对象 private ISubject subject = new SubjectImpl(); @Override public void request() { //在执行实际对象的request之前,还可以做一些其他操作 //是不是很像Spring 中的AOP啊 //-------------------------- //实际上是调用真实对象的request //只是这是代理对象帮忙去调用reqeust //很符合实际中的代理意义 subject.request(); //-------------------------- //还可以在实际对象操作结束之后,做一些其他操作 } }
public class Test { public static void main(String[] args) { ISubject proxy = new SubjectProxy(); proxy.request(); } }
完成,可以看到静态代理和动态代理的区别,静态代理,一个真实对象对应一个代理,如果有很多个真实对象需要代理,那么就需要很多个代理对象了,而动态代理的作用就在于此,他有一个总代理,可由代理工厂根据进入的代理类来得到代理对象。
呵呵~~
Spring事务属性说明
Spring事务属性配置属性说明如下:
PROPAGATION_REQUIRED 【支持当前事务,如果当前没有事务,就新建一个事务。(常用)】 PROPAGATION_SUPPORTS 【支持当前事务,如果当前没有事务,就以非事务方式执行】 PROPAGATION_MANDATORY 【支持当前事务,如果当前没有事务,就抛出异常】 PROPAGATION_REQUIRES_NEW 【新建事务,如果当前存在事务,把当前事务挂起】 PROPAGATION_NOT_SUPPORTED 【以非事务方式执行操作,如果当前存在事务,就把当前事务挂起】 PROPAGATION_NEVER 【以非事务方式执行,如果当前存在事务,则抛出异常】 PROPAGATION_NESTED 【如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作】 -Exception表示有Exception抛出时,事务回滚。-代表回滚+就代表提交 readonly 就是read only, 设置操作权限为只读,一般用于查询的方法,优化作用 |