#
由于Jboss默认的数据库为HypersonicDB,很多人,包括我,对它都不是十分了解,只知道它是java写的,使用起来不是很方便,本人最近在学EJB,所以研究了一下。
我在网上找了很多资料包括什么《JBOSS 数据源设置大全》啊,一类的文章,都不能成功将默认的数据库改为Oricle10g(别的数据库能否成功我没有试过),也就是我用的数据库,所以自己查阅了国外的一些BBS,总结了一下经验,贡献给chinajavalab。
1.删除Jboss\server\default\deploy下的hsql-ds.xml,从Jboss\docs\examples\jca中复制一个oracle-ds.xml过来,修改里面的属性;connection-url,driver-class,user-name,pssword,其中jndi-name最好设置成DefaultDS,这样可以方便后面几个xml文件的修改
2.删除Jboss\server\default\deploy\jms下的一切有关HSQL的文件,共有两个,
从Jboss\docs\examples\jms中复制一个oracle-jdbc2-service.xml过来,将<depends>中的name改为DefaultDS,或者你自己设置的jndi-name
3.进入Jboss\server\default\conf,如果你将jndi-name设置成DefaultDS的话,就不用设置login-config.xml了,否则要设置,将里面的DefaultDS更换成你的jndi-name,后面的xml文件也要注意jndi-name,后面就不再提示了
4.修改jboss-service.xml,将<!--attribute name="Pad">true</attribute--> 的注释去掉
5.修改standardjbosscmp-jdbc.xml,将datasource-mapping设置成Oracle9i,这里不管你用的是9i还是10g都要设置成9i,jboss4中目前还没有10g的相关内容,我用的是10g,没有问题的,关键是你的dirver包一定要是class12.jar,并将它放进Jboss\server\default\lib中
6.修改standardjaws.xml,将type-mapping设置为Oracle9i,增加
<type-mapping-definition>
<name>Oracle9i</name>
<mapping>
.
.
中间的内容到standardjbosscmp-jdbc.xml中的Oracle9i里找,复制过来
,只要其中<mapping>的内容,其他不要
.
.
</mapping>
</type-mapping-definition>
好了,重新启动你的jboss,部署一个EJB试一试,如果有异常,表示你还没有配置正确
Sun发布的JDK/JRE有两种版本,一种是.rpm.bin格式的,另一种则是.bin格式的,前者我没有试,但是我想应该是适合于rpm的,可能会安装到/usr里面去,而且自动化程度可以高一些。后者则完全是绿色软件,只是做一个解压的动作。下面我就来讲后者的安装全攻略。
1、首先我们要到Sun的网站上去下载JDK/JRE(点这里进入),最新的正式版本已经是6.0(也就是1.6),当然老的版本Sun也仍然提供下载,点上面的“Previous Releases”就可以找到了。下载.bin文件,下面假设这个文件的名字是jdk1.x.bin。
2、把安装文件解压出来。假设我们下载的文件保存在/opt下。
打开终端,运行以下命令:
引用:
cd /opt
chmod a+x jdk1.x.bin
./jdk1.x.bin
你会看到版权提示,不管它,按空格键翻页。然后会提示你是否同意版权协议[yes/no],此时输入yes,回车,安装程序就会把文件解压到当前目录下的jdk1.x这样的目录下面(JRE应该大体相同)。
3、让JDK/JRE支持中文。由于默认安装的JDK/JRE不带中文字体,不支持中文显示,所以我们要自行修改某些字体相关的配置,让它们支持中文。
设定字体有两种方法:
第一种方法是把你的中文字体目录做个连接到jdk/jre/lib/fonts里面,这种方法很简便。看命令:
引用:
cd /opt/jdk1.x/jre/lib/fonts
ln -s /usr/share/fonts/truetype/windows fallback (假设我们的中文字体放在/usr/share/fonts/truetype/windows目录里,这个目录里我放的是从Windows那边copy过来的字体)
为什么要做fallback这个连接,我也是从网上看到的,我想应该是Sun做的设定吧,设定JDK/JRE在运行时会到这个目录里去找那些非西方字体。这种方法对JDK/JRE 1.4/1.5/1.6都适用,但是由于没有在fontconfig.properties文件里面详细设定字体,所以这种方法显示出来的字体很难看。
第二种方法是把配置好的fontconfig.properties做个连接到jdk1.x/jre/lib里面。看命令:
引用:
cd /opt/jdk1.x/jre/lib
ln -s /etc/java/fontconfig.properties (假设我们的fontconfig.properties放在/etc/java目录里)
这种方法对JDK/JRE 1.4/1.5/1.6都适用,只不过1.4版本的文件名是font.properties而不是fontconfig.properties。当然你也可以直接把fontconfig.properties文件复制到/opt/jdk1.x/jre/lib里面,这样就不用做连接,但是如果你同时安装几个不同版本的JDK,还是做连接比较方便。在下面我会把我配置好的font.properties和fontconfig.properties的内容贴出来,大家稍作修改就可以用了。
3、让Web浏览器支持Java插件(也就是支持Java Applets)。
做一个连接就可以了。看命令:
引用:
cd /usr/lib/firefox/plugins (Ubuntu的firefox插件目录在这里,其它版本以此参考)
ln -s /opt/jdk1.x/jre/plugin/i386/ns7/libjavaplugin_oji.so
然后运行firefox,在地址栏里打入about:plugins,回车,可以看到firefox的插件列表里已经有了Java插件。
如果你用的是其它的浏览器,方法大体也差不多,就是进入浏览器的plugins目录,做一个连接。不过要注意的是,如果你用的浏览器是 mozilla 1.4/netscape 7.0以上的版本,用上面的命令没问题,但是如果你用的浏览器是mozilla 1.2/netscape 7.0以下的版本,Sun有提供另一个插件。这样的话,命令就要改一下了:
引用:
cd /usr/lib/mozilla/plugins
ln -s /opt/jdk1.x/jre/plugin/i386/ns7-gcc29/libjavaplugin_oji.so
4、让Web浏览器支持Java Web Start程序。(可选安装)
如果你不知道Java Web Start程序是什么,看这里:
http://www.stcore.com/java/2006/06/18/1150640682d28890.html
所谓安装,其实就是添加一个mimetype(类似于文件关联),让浏览器知道,遇到Java Web Start程序该用什么程序来处理。
对应mozilla/netscape浏览器的方法:
点击菜单:Edit->Preferences->Navigator->Helper Applications
然后新建一个mimetype:
mimetype是:application/x-java-jnlp-file
extention是:jnlp
关联程序是:/opt/jdk1.x/jre/bin/javaws
对应firefox浏览器的方法:
由于firefox没有直接添加mimetype的方法,所以要改的话需要安装一个Mime Type Editor扩展,看这里:
http://forums.mozine.org/index.php?showtopic=5521
5、为firefox浏览器加入Java Console菜单项。(可选安装)
mozilla/netscape装好java插件之后就有Java Console菜单项,可以方便地调用Java控制台,这对程序员调试程序有用。但是firefox还没有这个菜单项,添加的方法就是解压一个zip文件到firefox/extension目录。现在我们就来添加,看命令:
引用:
cd /usr/lib/firefox/extensions
unzip /opt/jdk1.x/jre/lib/deploy/ffjcext.zip
重启firefox,就可以看到工具菜单里多了一个Java Console菜单项。
JDK/JRE 1.5及以下版本并没有提供这个firefox扩展,如果要安装的话到这里安装:
https://addons.mozilla.org/firefox/141/
6、把Java工具加入系统菜单。(可选安装)
Ubuntu自带的JDK/JRE会在系统菜单中添加两个Java工具,就是Java Plugin Control Panel和Java Policy Tool。下面我们也为自己安装的JDK/JRE添加两个菜单项。
在Ubuntu的主菜单上点击右键->编辑菜单->首选项->新建项目:
第一项:
图标是:/opt/jdk1.x/jre/plugin/desktop/sun_java.png
名称是:Java Plugin Control Panel (这个随便写)
命令是:/opt/jdk1.x/jre/bin/ControlPanel
第二项:
图标是:/opt/jdk1.x/jre/plugin/desktop/sun_java.png
名称是:Java Policy Tool (这个随便写)
命令是:/opt/jdk1.x/jre/bin/policytool
7、添加JAVA_HOME/JRE_HOME环境变量。(Java开发人员必备)
这里以最常用的bash命令解释器为例,编辑用户目录下的.bashrc或.profile文件。如果你想在所有用户的shell下都生效,就编辑/etc/profile文件。同样都是加入以下内容:
引用:
export JAVA_HOME=/opt/jdk1.x
export JRE_HOME=/opt/jdk1.x/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
至此,Sun JDK/JRE在Linux上的安装过程结束。
DAO 类是线程安全的,它的所有操作都通过调用 DbExecutor 对象来执行。每次操作,DAO 都会从 DbExecutorFactory 中获得一个 DbExecutor 对象。DAO 要做的就是保证做完操作之后都要执行 DbExecutor 对象的 close 方法。
DbExecutor 是一个接口,它的大部分方法和 DAO 差不多。它包含一个数据库连接,当连接关闭时,DbExecutor 对象的生命周期也就结束了。OraDbExecutor 是 DbExecutor 的一个实现。
OraDbExecutor.java - 构造函数
- public OraDbExecutor(String dsName, Connection conn) {
- this.dsName = dsName;
- this.connection = conn;
- }
当创建 DbExecutor 实例时,DbExecutorFactory 先从 ConnectionFactoryBuilder 获得一个 ConnectionFactory 对象,然后从ConnectionFactory 获取一个数据库连接,用来创建 DbExecutor。当然,连接每个数据库的 ConnectionFactory 对象只有一个。
ConnectionFactoryBuilder.java - build()
- publicsynchronized ConnectionFactory build(String dsName) throws ConfigErrorException {
- if (factoryCache.get(dsName) == null) {
- DataSourceCollection sources = Configurator.getDataSources();
- DataSource ds = sources.getDataSource(dsName);
- if (ds == null) {
- thrownew ConfigErrorException("没有找到数据源 " + dsName);
- }
- factoryCache.put(dsName, buildFactory(ds));
- }
- return (ConnectionFactory) factoryCache.get(dsName);
- }
创建了一个 DAO 类用来做所有的事情,包括查询。查询方法如下:
java 代码 - public List query(Class clazz, String sql, List params) throws DAOException;
第一个参数是用来接受封装的类。 有时候仅查询一个字段,根本不用封装:
java 代码 - public List query(String sql, List params) throws DAOException;
如果封装,就要考虑查询结果字段到对象属性的映射关系。根据公司的数据库设计规范, 单词之间用下划线连起来。所以简单的替换一下就可以了。比如 USER_NAME 字段就映 射到 userName 属性。
如果查询结果中的字段有多,那这个字段的值就只好丢弃;如果类的属性有多,也不会给 它赋值。
分页查询。有时候会用到分页查询,所以添加了一个方法:
java 代码 - public Page queryPage(Class clazz, String sql, List params, int pageIndex, int pageSize)
- throws DAOException;
Page 对象除了包含查询结果外还有 totalNum 属性,表示查询总结果数。
表格封装的查询。有时候查询语句是动态生成的,没法确定查询结果的字段个数,用类来 封装显然不合适。于是定义了一个通用的表格结构用来封装,并添加了 queryTable() 方法: java 代码 - public DataTable queryTable(String sql) throws DAOException;
- public DataTable queryTable(String sql, List params, int pageIndex, int pageSize)
- throws DAOException;
DataTable 对象包含的其实就是一堆 HashMap。不过它同 Page 一样有一个查询总结果数, 而且添加了一些方法方便提取数据。这种查询的使用方式如下:
java 代码 - DAO dao = DAO.getDAO(SOURCE_NAME);
- DataTable table = dao.queryTable("select * from tt_test");
- assertEquals(6, table.getColumns());
- Map row = table.query("name", "张三丰");
- assertNotNull(row);
静态字段作为映射关系配置。有些字典表或配置表,一开始就被全部读入并缓存起来。为 了少写代码,DAO 提供将静态字段 TN 作为表名来查询的方式。如果类中存在 String 类型的 静态字段 TN,则可以使用这个方法:
java 代码 - public List query(Class clazz) throws DAOException;
|
没有哪个 DAO 能够包揽所有的数据库管理。每种 DAO 都有各自的定位。我们公司的项目有这样一些特点:
- 所用数据库都是 Oracle;
- 使用一些已有的数据库表;
- 查询语句要经过优化,DBA 要对其字斟句酌;
- 同时连接多个数据库。
我们的项目大都会用到一些其他系统现有的表。有的表包含四五十个字段,而对于某些业务逻辑来讲只需要查询一两个字段的值。DBA 强烈反对“select * ”,对关联查询、嵌套查询的性能要求也很严格。所以像 Hibernate 这样自动生成 SQL 语句的 DAO 自然不敢用。我们需要自己设计一个 DAO。
本着够用就行的原则,我们设计的 DAO (下面简称 DAO)先定下一个很低的目标:实现数据库连接管理,SQL 语句由使用者提供,将查询结果进行简单的封装。
数据库连接管理的具体设计是:
1、使用 XML 配置文件配置数据库连接;
2、支持 JDBC 和 JNDI(主要针对 WebLogic 的连接池) 两种方式创建数据库连接;
3、对同时连接多个数据库进行管理;
4、使用者不需关心数据库连接的创建和关闭。
对 XML 配置文件的设计:
DAO 配置文件用来配置数据库连接。鉴于当前的目标,DAO 没有映射关系配置。
配置文件将数据库抽象为“数据源”(DataSource),DAO 管理的是数据源。一个项目中可以存在多个数据源。数据源包含一个或多个连接配置,但运行时只会启用其中的一个,这样是为了方便修改配置,像 Rails 的 数据库配置文件中同时配置了开发环境、测试环境和产品环境三中数据库连接,一样的道理。
连接配置有 JNDI 和 JDBC 两种类型,分别需要不同的参数。JNDI 配置需要 JNDI 服务器、InitialContextFactory 类和 JNDI 名称三个参数,而JDBC 配置需要 Driver、url、用户名和密码四个参数。密码暂时不考虑加密,采用明文的方式。下面是一个配置文件的例子:
xml 代码
- <?xml version="1.0" encoding="GB2312" ?>
- <!DOCTYPE dao-config PUBLIC
- "-//Chinacreator, Ltd.//Data Access Object Library 1.2//CN" "dao-config.dtd">
-
- <dao-config>
-
- <datasource name="local_mysql" connection="default">
- <description>数据源1</description>
- <connection name="default" type="jdbc">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost/test"/>
- <property name="username" value="user"/>
- <property name="password" value="user"/>
- </connection>
- </datasource>
-
- <datasource name="demo" connection="jdbc_connection">
- <description>数据源2</description>
-
- <connection name="jndi_connection" type="jndi">
- <description>JNDI 方式</description>
- <property name="driver" value="weblogic.jndi.WLInitialContextFactory"/>
- <property name="server" value="t3://127.0.0.1:7010"/>
- <property name="jndiname" value="jndi/name"/>
- </connection>
-
- <connection name="jdbc_connection" type="jdbc">
- <description>JDBC 方式</description>
- <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
- <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:SidName"/>
- <property name="username" value="username"/>
- <property name="password" value="password"/>
- </connection>
-
- <connection name="pooled_jdbc" type="jdbc">
- <description>带连接池的 JDBC 方式</description>
- <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
- <property name="url" value="jdbc:oracle:thin:@172.16.168.85:1521:ora9i01"/>
- <property name="username" value="username"/>
- <property name="password" value="password"/>
- <property name="usepool" value="true"/>
- <property name="poolsize" value="2"/>
- </connection>
- </datasource>
- </dao-config>
那么使用者如何使用 DAO 执行 SQL 呢?下面是一个最简单的例子:
java 代码
- DAO dao = DAO.getDAO("demo");
- List list = dao.query("select areaname from tb_pub_area_code");
- assertEquals("长沙", list.get(0));
在这个例子中,DAO 根据配置文件找到数据源“demo”(17行),再根据数据源的 connection 属性找到名为
"jdbc_connection" 的连接配置(27行),然后连接到
"jdbc:oracle:thin:@127.0.0.1:1521:SidName" (30行)进行查询。
下面是当前网页应用程序应该出现的地方:
基于表单的交互
表单是很慢的,非常慢。尝试编辑位于
del.icio.us
上面的一个书签?点击编辑链接打开一个编辑书签的表单页面,然后编辑你的内容并点击提交按钮等待整个提交过程结束,最后返回上一页并向下滚动到你刚才编辑的书签那里查看内容是否已经正确更改。那
AJAX
呢?点击编辑链接马上开始更改标签内容,点击提交按钮开始异步传输标签编辑的内容并立即看到更改后的内容而无需重载整个页面。
深层树状导航
总而言之,带有深层树状导航的应用程序通常是一个噩梦。在大多数情况中简单平直的拓扑结构以及搜索
/
标记可以很好的工作。但是如果一个应用程序真正使用深层树状导航,使用
JavaScript
来管理拓扑
ui(user interface
用户接口
)
,则使用
Ajax
懒加载深层数据可以降低服务器的负载。举例来说,为了阅读一个只有一行的结果来加载整个一个新页面是非常耗时的。
实时用户对用户通讯
在一个允许用户创建实时讨论的信息公告系统中,
迫使用户一次又一次的更新完页面看到答复是非常愚蠢的。回复应该是实时的,用户不应被迫总是去痴迷于刷新操作。即使是
gmail
这个已经对以前像
hotmail/yahoo mail
的收件箱刷新,刷新收件箱标记的操作有所改进,也并没有充分的使用
Ajax
的功能来提示有新邮件到达。
投票、是否选择、等级评价
如果
Ajax
提交过程没有一个协调的
UI
提示是非常糟糕的,通过使用
Ajax
来提交一个调查或是否选择可以减少提交过程等待的痛苦。通过减少点击的等待时间,
Ajax
应用程序变得越来越有交互性
-
如果要用
40
秒来提交一个投票,除非非常在意的话大多数人会选择放弃。如果只花
1
秒呢,非常大比例的人会乐于参加投票的。(我在
Netflix versus
有
2008
张电影投票在
IMDb.com
有
210
张电影投票)
过滤和复杂数据操作
应用一个过滤、按日期排序、按日期和姓名排序、打开或关闭过滤器等等。任何一种高交换型操作应该交给
JavaScript
来处理而不是通过向服务器来提交一系列的请求。在查找或者操作大量数据的时候带来的视图上的改变最多不会超过
30
秒,
Ajax
真的使这些操作加速了。
普通录入时的提示/
自动补齐
一些软件
/JavaScript
是擅长于帮助用户完成键入相同的文字或可以预测的文字的工作的。在
del.icio.us
和
Gmail
中该功能是非常有益的,可以用来快速增加标记
/email
等。
对于一个频繁使用的应用程序诸如网页邮件客户端或博客阅读器来说,用户有充足的时间来学习如何使用新的UI概念但是他们却无法接受一个非常缓慢的反应速度。这种应用为Ajax变的更加普及起到了一个完美的杠杆作用。随着用户使用频率的增加,更多的Ajax部件应该加强用户的使用体验。
但是对于网页应用程序来说,把每件事甚至任何事都用JavaScript来实现也是没有意义的。Ajax只是针对一些特定的环境才能带来显著的帮助。在Ajax出现之前网页应用程序已经可以工作的很好了并且目前在网页开发中Ajax还存在着许多的缺陷和缺点。就算不从服务器端取得一个异步的信息数据流一个平直的html网页日志也可以工作的很好。对于文档或文档之间的跳转来说,老旧的纯HTML仍然是最好的选择。简单或很少使用的应用程序就算不用JavaScript同样可以很好的工作。
下面是一些不应该用到Ajax
的地方:
简单的表单
就算表单是
Ajax
技术的最大受益人,一个简单内容的表单,或提交订货单,或一次性的很少用到的表单都不应该使用以
Ajax
驱动的表单提交机制。总的来说,如果一个表单不是很长用,或已经工作的很好,那么就算使用
Ajax
也没有什么帮助。
搜索
实时搜索带来的痛苦要远大于他带来的帮助。这就是为什么
Google Suggest
还处于
beta
测试而并没有放在主页上的原因。在
Start.com Live.com
上搜索的时候你是不能使用返回按钮来查看上一次搜索或返回上一页的。或许还没有人来完成这项工作,但是完成这个工作应该是很困难的至少是不太明知的或者会因此带来更多的麻烦。(译注:现在已经有很多开源的框架可以实现历史记录功能)
基本导航
总的来说,使用
Ajax
为一个基础的网站
/
程序做导航是一个可怕的念头。谁会把用来使自己的程序变的更好的时间花在编写代码模仿浏览器的行为上面?在基础页面中导航的操作中
JavaScript
是没有用的。
替换大量的信息
Ajax
可以不用整页刷新来动态更新页面中改变的一小部分。但是如果一页上的大部分内容都需要更新,那为什么不从服务器那里获得一个新页面呢?
显示操作
虽然看上去
Ajax
是一个纯
UI
技术,其实不是这样的。他实际上是一个数据同步、操作、传输的技术。要想得到一个稳定的干净的网页程序,不使用
Ajax/JavaScript来直接完成用户接口是明智的。JavaScript可以分散分布并简单的操作XHTML/HTML DOM,根据CSS规则来决定如何让UI显示数据。查看
来查看如何使用
CSS
来替代
JavaScript
来控制数据的显示。
无用的网页小部件
滑块选择控件、拖拽控件、弹性控件(此处原文为
bouncies
,不知指为何物?)、鼠标样式、天气预报控件,这些小部件应该可以被更直接的控件代替或者为了整洁干脆整个去掉。为了选择一种颜色,也许滑块选择控件可以选择一个正确的阴影颜色,但是在一个商店中选择一个价格,使用滑块选择控件选到分这个单位对于用户来说有点过分。
建立表:
CREATE TABLE [TestTable] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[FirstName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
[LastName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
[Country] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Note] [nvarchar] (2000) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
插入数据:(2万条,用更多的数据测试会明显一些)
SET IDENTITY_INSERT TestTable ON
declare @i int
set @i=1
while @i<=20000
begin
insert into TestTable([id], FirstName, LastName, Country,Note) values(@i, 'FirstName_XXX','LastName_XXX','Country_XXX','Note_XXX')
set @i=@i+1
end
SET IDENTITY_INSERT TestTable OFF
-------------------------------------
分页方案一:(利用Not In和SELECT TOP分页)
语句形式:
SELECT TOP 10 *
FROM TestTable
WHERE (ID NOT IN
(SELECT TOP 20 id
FROM TestTable
ORDER BY id))
ORDER BY ID
SELECT TOP 页大小 *
FROM TestTable
WHERE (ID NOT IN
(SELECT TOP 页大小*页数 id
FROM 表
ORDER BY id))
ORDER BY ID
-------------------------------------
分页方案二:(利用ID大于多少和SELECT TOP分页)
语句形式:
SELECT TOP 10 *
FROM TestTable
WHERE (ID >
(SELECT MAX(id)
FROM (SELECT TOP 20 id
FROM TestTable
ORDER BY id) AS T))
ORDER BY ID
SELECT TOP 页大小 *
FROM TestTable
WHERE (ID >
(SELECT MAX(id)
FROM (SELECT TOP 页大小*页数 id
FROM 表
ORDER BY id) AS T))
ORDER BY ID
-------------------------------------
分页方案三:(利用SQL的游标存储过程分页)
create procedure XiaoZhengGe
@sqlstr nvarchar(4000), --查询字符串
@currentpage int, --第N页
@pagesize int --每页行数
as
set nocount on
declare @P1 int, --P1是游标的id
@rowcount int
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页
set @currentpage=(@currentpage-1)*@pagesize+1
exec sp_cursorfetch @P1,16,@currentpage,@pagesize
exec sp_cursorclose @P1
set nocount off
其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
建议优化的时候,加上主键和索引,查询效率会提高。
通过SQL 查询分析器,显示比较:我的结论是:
分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
分页方案一:(利用Not In和SELECT TOP分页) 效率次之,需要拼接SQL语句
分页方案三:(利用SQL的游标存储过程分页) 效率最差,但是最为通用
在实际情况中,要具体分析。
这些天开发一个项目,服务器是tomcat,操作系统是xp,采用的是MVC架构,模式是采用Facade模式,总是出现乱码,自己也解决了好多 天,同事也帮忙解决,也参考了网上众多网友的文章和意见,总算是搞定。但是好记性不如烂笔杆,所以特意记下,以防止自己遗忘,同时也给那些遇到同样问题的 人提供一个好的参考途径:
(一) JSP页面上是中文,但是看的是后是乱码:
解决的办法就是在JSP页面的编码的地方<%@ page language="java" contentType="text/html;charset=GBK" %>,因为Jsp转成Java文件时的编码问题,默认的话有的服务器是ISO-8859-1,如果一个JSP中直接输入了中文,Jsp把它当作 ISO8859-1来处理是肯定有问题的,这一点,我们可以通过查看Jasper所生成的Java中间文件来确认
(二) 当用Request对象获取客户提交的汉字代码的时候,会出现乱码:
解决的办法是:要配置一个filter,也就是一个Servelet的过滤器,代码如下:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
/**
* Example filter that sets the character encoding to be used in parsing the
* incoming request
*/
public class SetCharacterEncodingFilter implements Filter {
/**
* Take this filter out of service.
*/
public void destroy() {
}
/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)throws IOException, ServletException {
request.setCharacterEncoding("GBK");
// 传递控制到下一个过滤器
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
}
配置web.xml
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>SetCharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
如果你的还是出现这种情况的话你就往下看看是不是你出现了第四中情况,你的Form提交的数据是不是用get提交的,一般来说用post提交的话是没有问题的,如果是的话,你就看看第四中解决的办法。
还有就是对含有汉字字符的信息进行处理,处理的代码是:
package dbJavaBean;
public class CodingConvert
{
public CodingConvert()
{
//
}
public String toGb(String uniStr){
String gbStr = "";
if(uniStr == null){
uniStr = "";
}
try{
byte[] tempByte = uniStr.getBytes("ISO8859_1");
gbStr = new String(tempByte,"GB2312");
}
catch(Exception ex){
}
return gbStr;
}
public String toUni(String gbStr){
String uniStr = "";
if(gbStr == null){
gbStr = "";
}
try{
byte[] tempByte = gbStr.getBytes("GB2312");
uniStr = new String(tempByte,"ISO8859_1");
}catch(Exception ex){
}
return uniStr;
}
}
你也可以在直接的转换,首先你将获取的字符串用ISO-8859-1进行编码,然后将这个编码存放到一个字节数组中,然后将这个数组转化成字符串对象就可以了,例如:
String str=request.getParameter(“girl”);
Byte B[]=str.getBytes(“ISO-8859-1”);
Str=new String(B);
通过上述转换的话,提交的任何信息都能正确的显示。
(三) 在Formget请求在服务端用request. getParameter(“name”)时返回的是乱码;按tomcat的做法设置Filter也没有用或者用 request.setCharacterEncoding("GBK");也不管用问题是出在处理参数传递的方法上:如果在servlet中用 doGet(HttpServletRequest request, HttpServletResponse response)方法进行处理的话前面即使是写了:
request.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=GBK");
也是不起作用的,返回的中文还是乱码!!!如果把这个函数改成doPost(HttpServletRequest request, HttpServletResponse response)一切就OK了。
同样,在用两个JSP页面处理表单输入之所以能显示中文是因为用的是post方法传递的,改成get方法依旧不行。
由此可见在servlet中用doGet()方法或是在JSP中用get方法进行处理要注意。这毕竟涉及到要通过浏览器传递参数信息,很有可能引起常用字符集的冲突或是不匹配。
解决的办法是:
1) 打开tomcat的server.xml文件,找到区块,加入如下一行:
URIEncoding=”GBK”
完整的应如下:
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK"/>
2)重启tomcat,一切OK。
需要加入的原因大家可以去研究 $TOMCAT_HOME/webapps/tomcat-docs/config/http.html下的这个文件就可以知道原因了。需要注意的是:这 个地方如果你要是用UTF-8的时候在传递的过程中在Tomcat中也是要出现乱码的情况,如果不行的话就换别的字符集。
(四) JSP页面上有中文,按钮上面也有中文,但是通过服务器查看页面的时候出现乱码:
解决的办法是:首先在JSP文件中不应该直接包含本地化的消息文本,而是应该通过<bean:message>标签从Resource Bundle中获得文本。应该把你的中文文本放到Application.properties文件中,这个文件放在WEB-INF/classes/* 下,例如我在页面里有姓名,年龄两个label,我首先就是要建一个Application.properties,里面的内容应该是name=”姓名” age=”年龄”,然后我把这个文件放到WEB-INF/classes/properties/下,接下来根据 Application.properties文件,对他进行编码转化,创建一个中文资源文件,假定名字是 Application_cn.properties。在JDK中提供了native2ascii命令,他能够实现字符编码的转换。在DOS环境中找到你 放置Application.properties的这个文件的目录,在DOS环境中执行一下命令,将生成按GBK编码的中文资源文件 Application_cn.properties:native2ascii ?Cencoding gbk Application.properties Application_cn.properties执行以上命令以后将生成如下内容的Application_cn.properties文件: name=\u59d3\u540d age=\u5e74\u9f84,在Struts-config.xml中配置:<message-resources parameter="properties.Application_cn"/>。到这一步,基本上完成了一大半,接着你就要在JSP页面上写 <%@ page language="java" contentType="text/html;charset=GBK" %>,到名字的那个label是要写<bean:message key=”name”>,这样的化在页面上出现的时候就会出现中文的姓名,年龄这个也是一样,按钮上汉字的处理也是同样的。
(五) 写入到数据库是乱码:
解决的方法:要配置一个filter,也就是一个Servelet的过滤器,代码如同第二种时候一样。
如果你是通过JDBC直接链接数据库的时候,配置的代码如下:jdbc:mysql://localhost:3306/workshopdb? useUnicode=true&characterEncoding=GBK,这样保证到数据库中的代码是不是乱码。
如果你是通过数据源链接的化你不能按照这样的写法了,首先你就要写在配置文件中,在tomcat 5.0.19中配置数据源的地方是在C:\Tomcat 5.0\conf\Catalina\localhost这个下面,我建立的工程是workshop,放置的目录是webapp下面, workshop.xml的配置文件如下:
<!-- insert this Context element into server.xml -->
<Context path="/workshop" docBase="workshop" debug="0"
reloadable="true" >
<Resource name="jdbc/WorkshopDB"
auth="Container"
type="javax.sql.DataSource" />
<ResourceParams name="jdbc/WorkshopDB">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>100</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>30</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>10000</value>
</parameter>
<parameter>
<name>username</name>
<value>root</value>
</parameter>
<parameter>
<name>password</name>
<value></value>
</parameter>
<!-- Class name for mm.mysql JDBC driver -->
<parameter>
<name>driverClassName</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value><![CDATA[jdbc:mysql://localhost:3306/workshopdb
?useUnicode=true&characterEncoding=GBK]]></value>
</parameter>
</ResourceParams>
</Context>
粗体的地方要特别的注意,和JDBC直接链接的时候是有区别的,如果你是配置正确的化,当你输入中文的时候到数据库中就是中文了,有一点要注意的是你在显 示数据的页面也是要用<%@ page language="java" contentType="text/html;charset=GBK" %>这行代码的。需要注意的是有的前台的人员在写代码的是后用Dreamver写的,写了一个Form的时候把他改成了一个jsp,这样有一个地方 要注意了,那就是在Dreamver中Action的提交方式是request的,你需要把他该过来,因为在jsp的提交的过程中紧紧就是POST和 GET两种方式,但是这两种方式提交的代码在编码方面还是有很大不同的,这个在后面的地方进行说明。3
以上就是我在开发系统中解决中文的问题,不知道能不能解决大家的问题,时间匆忙,没有及时完善,文笔也不是很好,有些地方估计是词不达意。大家可以给我意见,希望能共同进步。
Oracle数据库有三种标准的备份方法,它们分别是导出/导入(EXP/IMP)、热备份和冷备份。导出备件是一种逻辑备份,冷备份和热备份是物理备份。
一、 导出/导入(Export/Import)
利用Export可将数据从数据库中提取出来,利用Import则可将提取出来的数据送回到Oracle数据库中去。
1、 简单导出数据(Export)和导入数据(Import)
Oracle支持三种方式类型的输出:
(1)、表方式(T方式),将指定表的数据导出。
(2)、用户方式(U方式),将指定用户的所有对象及数据导出。
(3)、全库方式(Full方式),瘵数据库中的所有对象导出。
数据导入(Import)的过程是数据导出(Export)的逆过程,分别将数据文件导入数据库和将数据库数据导出到数据文件。
2、 增量导出/导入
增量导出是一种常用的数据备份方法,它只能对整个数据库来实施,并且必须作为SYSTEM来导出。在进行此种导出时,系统不要求回答任何问题。导出文件名缺省为export.dmp,如果不希望自己的输出文件定名为export.dmp,必须在命令行中指出要用的文件名。
增量导出包括三种类型:
(1)、“完全”增量导出(Complete)
即备份三个数据库,比如:
exp system/manager inctype=complete file=040731.dmp
(2)、“增量型”增量导出
备份上一次备份后改变的数据,比如:
exp system/manager inctype=incremental file=040731.dmp
(3)、“累积型”增量导出
累计型导出方式是导出自上次“完全”导出之后数据库中变化了的信息。比如:
exp system/manager inctype=cumulative file=040731.dmp
数据库管理员可以排定一个备份日程表,用数据导出的三个不同方式合理高效的完成。
比如数据库的被封任务可以做如下安排:
星期一:完全备份(A)
星期二:增量导出(B)
星期三:增量导出(C)
星期四:增量导出(D)
星期五:累计导出(E)
星期六:增量导出(F)
星期日:增量导出(G)
如果在星期日,数据库遭到意外破坏,数据库管理员可按一下步骤来回复数据库:
第一步:用命令CREATE DATABASE重新生成数据库结构;
第二步:创建一个足够大的附加回滚。
第三步:完全增量导入A:
imp system/manager inctype=RESTORE FULL=y FILE=A
第四步:累计增量导入E:
imp system/manager inctype=RESTORE FULL=Y FILE=E
第五步:最近增量导入F:
imp system/manager inctype=RESTORE FULL=Y FILE=F
二、 冷备份
冷备份发生在数据库已经正常关闭的情况下,当正常关闭时会提供给我们一个完整的数据库。冷备份时将关键性文件拷贝到另外的位置的一种说法。对于备份Oracle信息而言,冷备份时最快和最安全的方法。冷备份的优点是:
1、 是非常快速的备份方法(只需拷文件)
2、 容易归档(简单拷贝即可)
3、 容易恢复到某个时间点上(只需将文件再拷贝回去)
4、 能与归档方法相结合,做数据库“最佳状态”的恢复。
5、 低度维护,高度安全。
但冷备份也有如下不足:
1、 单独使用时,只能提供到“某一时间点上”的恢复。
2、 再实施备份的全过程中,数据库必须要作备份而不能作其他工作。也就是说,在冷备份过程中,数据库必须是关闭状态。
3、 若磁盘空间有限,只能拷贝到磁带等其他外部存储设备上,速度会很慢。
4、 不能按表或按用户恢复。
如果可能的话(主要看效率),应将信息备份到磁盘上,然后启动数据库(使用户可以工作)并将备份的信息拷贝到磁带上(拷贝的同时,数据库也可以工作)。冷备份中必须拷贝的文件包括:
1、 所有数据文件
2、 所有控制文件
3、 所有联机REDO LOG文件
4、 Init.ora文件(可选)
值得注意的使冷备份必须在数据库关闭的情况下进行,当数据库处于打开状态时,执行数据库文件系统备份是无效的。
下面是作冷备份的完整例子。
(1) 关闭数据库
sqlplus /nolog
sql>connect /as sysdba
sql>shutdown normal;
(2) 用拷贝命令备份全部的时间文件、重做日志文件、控制文件、初始化参数文件
sql>cp
(3) 重启Oracle数据库
sql>startup
三、 热备份
热备份是在数据库运行的情况下,采用archivelog mode方式备份数据库的方法。所以,如果你有昨天夜里的一个冷备份而且又有今天的热备份文件,在发生问题时,就可以利用这些资料恢复更多的信息。热备份要求数据库在Archivelog方式下操作,并需要大量的档案空间。一旦数据库运行在archivelog状态下,就可以做备份了。热备份的命令文件由三部分组成:
1. 数据文件一个表空间一个表空间的备份。
(1) 设置表空间为备份状态
(2) 备份表空间的数据文件
(3) 回复表空间为正常状态
2. 备份归档log文件
(1) 临时停止归档进程
(2) log下那些在archive rede log目标目录中的文件
(3) 重新启动archive进程
(4) 备份归档的redo log文件
3. 用alter database bachup controlfile命令来备份控制文件
热备份的优点是:
1. 可在表空间或数据库文件级备份,备份的时间短。
2. 备份时数据库仍可使用。
3. 可达到秒级恢复(恢复到某一时间点上)。
4. 可对几乎所有数据库实体做恢复
5. 恢复是快速的,在大多数情况下爱数据库仍工作时恢复。
热备份的不足是:
1. 不能出错,否则后果严重
2. 若热备份不成功,所得结果不可用于时间点的恢复
3. 因难于维护,所以要特别仔细小心,不允许“以失败告终”。
代码清单
import java.io.*;
import java.net.*;
import java.util.*;
/**
* <p>title: 个人开发的api</p>
* <p>description: 将指定的http网络资源在本地以文件形式存放</p>
* <p>copyright: copyright (c) 2004</p>
* <p>company: newsky</p>
* @author magicliao
* @version 1.0
*/
public class httpget {
public final static boolean debug = true;//调试用
private static int buffer_size = 8096;//缓冲区大小
private vector vdownload = new vector();//url列表
private vector vfilelist = new vector();//下载后的保存文件名列表
/**
* 构造方法
*/
public httpget() {
}
/**
* 清除下载列表
*/
public void resetlist() {
vdownload.clear();
vfilelist.clear();
}
/**
* 增加下载列表项
*
* @param url string
* @param filename string
*/
public void additem(string url, string filename) {
vdownload.add(url);
vfilelist.add(filename);
}
/**
* 根据列表下载资源
*/
public void downloadbylist() {
string url = null;
string filename = null;
//按列表顺序保存资源
for (int i = 0; i < vdownload.size(); i++) {
url = (string) vdownload.get(i);
filename = (string) vfilelist.get(i);
try {
savetofile(url, filename);
}
catch (ioexception err) {
if (debug) {
system.out.println("资源[" + url + "]下载失败!!!");
}
}
}
if (debug) {
system.out.println("下载完成!!!");
}
}
/**
* 将http资源另存为文件
*
* @param desturl string
* @param filename string
* @throws exception
*/
public void savetofile(string desturl, string filename) throws ioexception {
fileoutputstream fos = null;
bufferedinputstream bis = null;
httpurlconnection httpurl = null;
url url = null;
byte[] buf = new byte[buffer_size];
int size = 0;
//建立链接
url = new url(desturl);
httpurl = (httpurlconnection) url.openconnection();
//连接指定的资源
httpurl.connect();
//获取网络输入流
bis = new bufferedinputstream(httpurl.getinputstream());
//建立文件
fos = new fileoutputstream(filename);
if (this.debug)
system.out.println("正在获取链接[" + desturl + "]的内容...\n将其保存为文件[" + filename + "]");
//保存文件
while ( (size = bis.read(buf)) != -1)
fos.write(buf, 0, size);
fos.close();
bis.close();
httpurl.disconnect();
}
/**
* 设置代理服务器
*
* @param proxy string
* @param proxyport string
*/
public void setproxyserver(string proxy, string proxyport) {
//设置代理服务器
system.getproperties().put("proxyset", "true");
system.getproperties().put("proxyhost", proxy);
system.getproperties().put("proxyport", proxyport);
}
/**
* 设置认证用户名与密码
*
* @param uid string
* @param pwd string
*/
public void setauthenticator(string uid, string pwd) {
authenticator.setdefault(new myauthenticator(uid, pwd));
}
/**
* 主方法(用于测试)
*
* @param argv string[]
*/
public static void main(string argv[]) {
httpget oinstance = new httpget();
try {
//增加下载列表(此处用户可以写入自己代码来增加下载列表)
oinstance.additem("http://www.ebook.com/java/网络编程001.zip","./网络编程1.zip");
oinstance.additem("http://www.ebook.com/java/网络编程002.zip","./网络编程2.zip");
oinstance.additem("http://www.ebook.com/java/网络编程003.zip","./网络编程3.zip");
oinstance.additem("http://www.ebook.com/java/网络编程004.zip","./网络编程4.zip");
oinstance.additem("http://www.ebook.com/java/网络编程005.zip","./网络编程5.zip");
oinstance.additem("http://www.ebook.com/java/网络编程006.zip","./网络编程6.zip");
oinstance.additem("http://www.ebook.com/java/网络编程007.zip","./网络编程7.zip");
//开始下载
oinstance.downloadbylist();
}
catch (exception err) {
system.out.println(err.getmessage());
}
}
}