Oracle ERP最佳技术实践
E-B USINESS S UITE
O RACLE核心应用技术
DB、PL/SQL要点荟萃
Author: 黄建华Jianhua.Huang
MSN: huajhua@https://www.doczj.com/doc/3313904344.html,
Creation Date: October 16, 2006
Last Updated: March 30, 2013
Document Ref:
Version: DRAFT 1A
Approvals:
Copy Number _____
Document Control
Change Record
Reviewers
Distribution
Note To Holders:
If you receive an electronic copy of this document and print it out, please write your
name on the equivalent of the cover page, for document control purposes.
If you receive a hard copy of this document, please write your name on the front
cover, for document control purposes.
Contents
Document Control .................................................................................................................. i i 1.特殊值、特殊字段、特殊对象、特殊语句.. (2)
1.1.Null值 (2)
1.2.With语句 (2)
1.3.SQL%变量 (3)
1.4.Sequence (3)
1.5.Table() (3)
2.连接处理:嵌套循环、Hash、排序合并 (5)
2.1.外连接 (5)
3.Transaction事务 (6)
3.1.回顾事务 (6)
3.2.自治事务 (6)
3.3.分布式事务和两阶段提交 (8)
4.Lock锁、Session会话、Process进程 (10)
4.1.Lock演示和检查 (10)
4.2.会话、进程、请求 (12)
5.自带的Application Server (14)
5.1.OC4J概述 (14)
5.2.配置和发布 (15)
6.MOD PL/SQL (18)
6.1.MOD PL/SQ基础 (18)
7.Java (19)
7.1.直接作为Procedure (19)
8.物化视图、高级复制 (20)
8.1.快照自动更新 (20)
8.2.高级复制基础 (21)
8.3.单主异步可更新MV (25)
8.4.多主异步复制 (31)
8.5.多主同步复制 (36)
8.6.其它常用SQL (37)
9.计划任务:DBMS_JOB、DBMS_SCHEDULER (39)
9.1.DBMS_JOB (39)
9.2.DBMS_JOB (39)
10.Data Guard (40)
10.1.Data Guard基础 (40)
11.高级队列:Streams AQ (42)
11.1.技术架构 (42)
12.Open and Closed Issues for this Deliverable (44)
Open Issues (44)
Closed Issues (44)
1.特殊值、特殊字段、特殊对象、特殊语句
1.1.Null值
1.1.1.说明
1、判断:必须用is null或者is not nulll,不能用=null,这个和C、Java等不同
2、赋值:可以用=null,或者=’’
3、参数:特别注意字段值和参数值都可能为空的情况,常用nvl函数处理后判断
数值nvl成FND_API.G_MISS_NUM或9.99E125
字符nvl成FND_API.G_MISS_CHAR或chr(0)
日期nvl成FND_API.G_MISS_DATE或TO_DATE('1','j')
1.1.
2.测试数据
SELECT * FROM scott.emp; --return 14 records
1.1.3.SQL例子:判断
SELECT * FROM scott.emp emp WHERE emp.mgr = 7698; --Return 5 records
SELECT * FROM scott.emp emp WHERE emp.mgr != 7698; --Return 8 records, not 9
SELECT * FROM scott.emp emp WHERE emp.mgr IS NULL; --Return 1 records
1.1.4.SQL例子:参数
通常情况下,当p_mgr为空时,应返回所有记录,即14条。写法如下:
SELECT *
FROM scott.emp emp
WHERE nvl(emp.mgr, 9.99e125) = nvl('&p_mgr', nvl(emp.mgr, 9.99e125));
但是,如果参数的含义是,为空时返回空的记录,那么写法如下:
SELECT *
FROM scott.emp emp
WHERE nvl(emp.mgr, 9.99e125) = nvl('&p_mgr', 9.99e125);
1.2.With语句
1.2.1.说明
在一个SQL中,如果要重复使用某一子查询,9i之后可以使用With语句了,它相当于提
前给子查询起一个别名,在接下来的SQL From中直接用该别名,这样可以大大简化
SQL语句,也可以集中处理一些参数。
需要数据库是9i并且客户端OCI版本大于9才可以。
1.2.2.最简单例子
以下例子最简单:
with a as(select1 f from dual) select * from a;
首先为select 1 f from dual起了个别名a,然后就可以在后面的SQL中直接From a。再
比如:
with a as(select1 f from dual),b as(select2 f from dual)
SELECT a.f, b.f FROM a, b WHERE a.f <= b.f;
1.3.SQL%变量
1.3.1.SQL%ROWCOUNT
获得刚刚执行的语句影响了多少行。
1.4.Sequence
1.4.1.说明
Seqence是Oracle中比较特别对象,和SQL Server及Access中的自动编号字段不同。
前者是个对象,可以通过SQL取得下一个序列得值,也可以在当前Session取得最近一
次取得的值,至于取出来的值怎么用,完全由程序控制;后者则是字段的数据类型,
在Insert到数据到表的时候,数据库自动为该字段赋下一个序列值,我们无法控制。
1.4.
2.跨库唯一序列
1、使用SYS_GUID()可以得到跨库唯一序列:SELECT SYS_GUID() OID FROM DUAL;
2、使用附加字符,如在Sequence后加不同的主机名或者特殊的后缀
3、在不同的主机用不同的START WITH、INCREMENT BY组和
1.5.Table()
1.5.1.说明
从9i开始可以使用Table()函数获得一个内存表,使用起来类似临时表,主要应用在查询
报表,效率问题:
平均效率最差的是Table(),它与其他两者对比效率相差几个数量级;其次为临时表,
而普通物理表的效率最优。而第一次访问效率则是Table()最好。
对于物理表,它的数据是存储在物理磁盘上的,但数据第一次read时,会被load到db
cache中去,根据LRU算法来决定这些数据是否会被置换出内存(如果建表时使用了
cache,则会一直存储在内存中)。我们这主要是考虑这些数据在内存中被扫描。由于
它的数据是会被所有会话共享的,所以就会存在锁和脏数据的问题。而由于它的数据
是结构化的,所以在内存中进行数据扫描时,效率是最高的。
对于临时表,它及它的索引都是创建在临时表空间上的。当在一个会话中第一次插入数据时,才开始在用户的默认临时表空间给他分配临时段,不同的会话会分配不同的临时段。这就决定的了各个会话的同一个临时表的数据不会相互影响。临时表的数据也是结构化的。第一次读取数据后,数据也被cache到db cache中。此外,在建表时可以通过参数指定它是事物级的还是会话级的,但是对查询效率来说是没什么影响的。还有一点,临时表的数据变化是不会产生redo log的(但会产生undo log),当然,这对查询效率也没有影响,致使顺带提一下。
对于Table()函数,实际上是将一个存储在内存中的对象(以流的方式存储)结构化以后,使这个对象能以表的方式查询。他对流对象的结构化转换就决定了它的效率大大逊于对普通表和临时表的查询效率。
1.5.
2.定义类型
CREATE OR REPLACE TYPE tp_test AS OBJECT
(
id Number,
NAME VARCHAR2(60)
);
CREATE OR REPLACE TYPE tp_test_table AS TABLE OF tp_test;
1.5.3.定义函数,产生数据
CREATE OR REPLACE FUNCTION fun_test_table(p_n IN NUMBER DEFAULT NULL) RETURN
tp_test_table AS
l_test tp_test_table := tp_test_table();
BEGIN
FOR i IN1 .. nvl(p_n, 100) LOOP
l_test.EXTEND();
l_test(l_test.COUNT) := tp_test(i, 'Name ' || i);
END LOOP;
RETURN l_test;
END;
1.5.4.测试使用
SELECT * FROM TABLE(fun_test_table(10)) a;
SELECT * FROM THE(SELECT fun_test_table(10) FROM dual) a;
不过,没法DML:
UPDATE TABLE(fun_test_table(10)) a SET https://www.doczj.com/doc/3313904344.html, = https://www.doczj.com/doc/3313904344.html, || ' Test'WHERE id = 1;
2.连接处理:嵌套循环、Hash、排序合并
2.1.外连接
2.1.1.说明
通常说的外连接,其实含义比较模糊。SQL标准具体分左连接、右连接、全连接;其中
全连接Oracle 10g才有,用得也少。
实际写PL/SQL,还是说“外连接”的,即A、B表的连接,到底是A.Column_Name =
B.Column_Name(+)还是A.Column_Name(+) = B.Column_Name。
判断原则如下:看需求,也就是哪个表的数据要全部出来,哪个表的数据有就出来没
有就算了,这时,后者放(+)。
注意,实际开发过程中,有时候还要具体看表里的数据,并不是所有的数据库表设计
都尽如人意。
2.1.2.测试数据
插入一条没有部门的员工:
INSERT INTO scott.emp
VALUES
('1000', 'TEST', 'CLERK', '', '', 400, '', '');
2.1.
3.SQL例子:统计每个部门的员工数
DEPT表的数据要全部出来,EMP仅仅用来计数,没有就是0,这时EMP表放(+):
SELECT a.deptno, a.dname, COUNT(b.empno)
FROM scott.dept a, scott.emp b
WHERE a.deptno = b.deptno(+)
GROUP BY a.deptno, a.dname;
2.1.4.SQL例子:给出每个员工及其部门名称
EMP表的数据要全部出来,DEPT仅仅用取部门名,没有就是空,这时DEPT表放(+):
SELECT b.empno, b.ename, a.dname
FROM scott.dept a, scott.emp b
WHERE a.deptno(+) = b.deptno;
3.Transaction事务
3.1.回顾事务
3.1.1.事务定义
数据库中的事务是具备以下属性的一系列操作:原子性、一致性、隔离性和持久性,
简称ACID。简单说起来就是:
1、一件事情,必须做完整,才能确认保存——Commit,否则必须退回到事情的起始
状态——Rollback。
2、在这件事情未确认保存或确认失败前,其它人——Session是不知道其在做什么。
3.1.2.理解事务
例子:从储蓄帐户转账 500 元到支票帐户。
这个过程可以细分为两个操作,从您的储蓄帐户取出 500 元,存 500 元存到您的支票
帐户里。如果两个操作都成功,您和银行都会满意。如果两个操作都失败,您们也不
必紧张,大家都可以接受这个结果,只要稍后再试一次就行了。
现在想象一下,如果在帐户转存操作过程中银行的计算机崩溃了,会发生什么情况?
首先,假设银行计算机崩溃正好发生在从储蓄帐户中取出 500 元后,但在存入支票帐
户之前。这样,您就会损失 500 元。现在假设另外一种情况:如果在 500 元记入支票
帐户后,但在从储蓄帐户中取出之前发生银行计算机崩溃,又会发生什么情况呢。您
会很高兴,但银行是不会接受的。
原子性:这两个操作必需同时成功或同时失败。
一致性:存入支票帐户的钱数应与从储蓄帐户中取出的钱数相等。
隔离性:与帐户转存并发执行的其它事务不应看到无效的中间状态。在此例中,如果
从储蓄帐户中取出 500 元,其它会话永远看不到这 500 元尚未存到支票帐户的情况
持久性:事务提交后,由事务进行的更新永远不会丢失。在事务提交之后,系统崩
溃、网络故障,甚至有人不小心拔出了电源线都不应造成更新丢失。大多数数据库通
过先将所有需要进行的更改写入持久存储的日记文件中,来确保持久性。只有在写入
日记文件后,才会提交事务。如果在事务提交后系统崩溃或有人从插座中拔出电源插
头,系统会读取其日志并重试所有非永久性的已提交事务,或尝试回滚所有已中止的
事务。
3.2.自治事务
3.2.1.理解自治事务
自治事务的简单理解:如果在程序A中调用B,通常情况下A和B是从属于同一事务;但
在某些情况下,在处理A过程中,有些不得不完成或者希望记下来的事情要Commit,
这时可以把B声明为“自治事务”,使其独立于当前A的事务。
要注意,A和B仍旧是一个Session,共享环境变量和系统资源。
3.2.2.Procedure例子:保存Log到表
如果想在程序运行过程中把调式等信息写入Log表,如果主程序自己遇到错误通常我们会Rollback,这时候实际上写到Log表的数据也被Rollback了,我们事后根本无法查到当时的Log。为此我们可以专门写个Procedure,并设置为自治事务,就可以使Log信息得到保存。
创建log表:
create sequence cux_log_message_s;
create table CUX_LOG_MESSAGES
(
LOG_MESSAGE_ID NUMBER not null,
SEQUENCE_NUM NUMBER not null,
APPLICATION_NAME VARCHAR2(100) not null,
PROGRAM_NAME VARCHAR2(100) not null,
MESSAGE_DATE DATE not null,
CONTENT VARCHAR2(4000)
);
创建Procedure:
CREATE PROCEDURE to_table(p_msg IN LONG,
p_seq IN NUMBER DEFAULT0,
p_app IN VARCHAR2DEFAULT'Default',
p_program IN VARCHAR2DEFAULT'Default',
p_date IN DATE DEFAULT SYSDATE) IS PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO cux_log_messages
(log_message_id,
sequence_num,
application_name,
program_name,
message_date,
content)
(SELECT cux_log_message_s.NEXTVAL,
p_seq,
p_app,
p_program,
p_date,
p_msg
FROM dual);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
测试脚本:
BEGIN
to_table('Log Message..1');
--to do anything here
ROLLBACK;
to_table('Log Message..2');
--to do anything here
COMMIT;
END;
验证脚本:SELECT * FROM cux_log_messages
可以看到,不管主调用是Rollback还是Commit,两个Message都成功存入表了。
3.3.分布式事务和两阶段提交
3.3.1.什么是分布式事务
如果事务只涉及单个数据库,事务的处理就简单了。遗憾的是,大多数企业不会把他
们所有的重要信息都存储在单个数据库中。在很多情形下,信息会分布在许多数据库
中。
例如,一个网络零售商就可能有一个存储在公司办公室的 Oracle 数据库中的客户帐户
信息数据库,而订单执行信息可能会存储在合作伙伴公司仓库的 SQL Server 数据库
中。当一个客户向这个网络零售商订货时,该客户的帐户应记入公司办公室的数据库
中,而订单记录应写入合作伙伴公司的 SQL Server 数据库中。如果总是要求客户支付
产品的费用而从不发货,网络零售商的信誉就会受到损害。因此,为了防止这种情况
的发生,更新应作为一个事务在这两个数据库中同时进行。如果任一个操作失败,每
数据库都将回滚它的事务部分。
这种类型的事务被称为分布式事务:一个涉及到多个独立数据库的事务,每个涉及到
的数据库都将提交它们的事务,如果有任何数据库无法提交它们的事务,则两个数据
库都将回滚其更新操作。
3.3.2.什么是两阶段提交
实现分布式事务的关键就是两阶段提交协议,负责该协议的是“事务协调器”,通常
它是数据库系统的一个内置组件,不需要我们关注。此协议分5个步骤执行:
1、应用程序调用“事务协调器”中的提交方法。
2、第一阶段,通知提交
“事务协调器”将联络事务中涉及的每个数据库,并通知它们准备提交事务。
3、数据库响应
每个数据库必须将自己置于以下2种状态:确保能在被要求提交事务时提交事务,或在
被要求回滚事务时回滚事务。然后将设置的结果通知“事务协调器”。
4、汇总响应
“事务协调器”收集来自数据库的所有响应。
5、第二阶段:执行提交
事务协调器将事务的结果通知给每个数据库。如果任一数据库做出否定响应,则事务
协调器会将一个回滚命令发送给事务中涉及的所有数据库;如果数据库都做出肯定响
应,则事务协调器会指示所有的数据库提交事务;一旦通知数据库提交,此后的事务
就不能失败了。
提交成功例子(资源管理器指数据库):
提交失败例子(资源管理器指数据库):
4.Lock锁、Session会话、Process进程
4.1.Lock演示和检查
4.1.1.测试数据
--创建表
Drop Table lock_test;
Create Table lock_test(f1 Number,f2 Varchar2(30));
--写入数据
BEGIN
INSERT INTO lock_test VALUES (1, 'Jack');
INSERT INTO lock_test VALUES (2, 'Leiko');
COMMIT;
END;
4.1.2.锁测试
--Session1:更新数据但不Commit
UPDATE lock_test t SET t.f1 = t.f1 WHERE t.f1 = 1;
--Session2:更新数据,发现一直在等待
UPDATE lock_test t SET t.f1 = t.f1 WHERE t.f1 = 1
--Session3:更新数据,发现一直在等待
UPDATE lock_test t SET t.f1 = t.f1 WHERE t.f1 = 1
4.1.3.查看所锁的ROWID
--检查锁及其等待的行ROWID
SELECT substr(o.owner, 1, 8) owner,
o.object_type object_type,
substr(o.object_name, 1, 18) object_name,
decode(l.locked_mode,
0,
'None',
1,
'Null',
2,
'Row-S',
3,
'Row-X',
4,
'Share',
5,
'S/Row-X',
6,
'Exclusive') locked_mode,
l.session_id sid,
l.oracle_username username,
l.os_user_name osuser,
to_char(s.logon_time, 'YYYY/MM/DD HH24:MI:SS') logon_time,
decode(s.row_wait_obj#,
-1,
NULL,
dbms_rowid.rowid_create(1,
s.row_wait_obj#,
s.row_wait_file#,
s.row_wait_block#,
s.row_wait_row#)) row_id FROM v$locked_object l, --gv$locked_object
all_objects o,
v$session s --gv$session
WHERE l.object_id = o.object_id
AND l.session_id = s.sid
--AND l.inst_id = s.inst_id
AND o.object_name = 'LOCK_TEST';
4.1.4.查看Session等待关系
--Session等待树型结构,改造自$ORACLE_HOME/rdbms/admin/utllockt.sql
With lock_holders As(
SELECT w.session_id waiting_session,
h.session_id holding_session,
w.lock_type,
h.mode_held,
w.mode_requested,
w.lock_id1,
w.lock_id2
FROM dba_locks w, dba_locks h
WHERE h.blocking_others = 'Blocking'
AND h.mode_held != 'None'
AND h.mode_held != 'Null'
AND w.mode_requested != 'None'
AND w.lock_type = h.lock_type
AND w.lock_id1 = h.lock_id1
AND w.lock_id2 = h.lock_id2
)
SELECT lpad(' ', 3 * (LEVEL - 1)) || waiting_session waiting_session,
lock_type,
mode_requested,
mode_held,
lock_id1,
lock_id2
FROM (SELECT *
FROM lock_holders
UNION
SELECT holding_session, NULL, 'None', NULL, NULL, NULL, NULL FROM lock_holders
MINUS
SELECT waiting_session, NULL, 'None', NULL, NULL, NULL, NULL FROM lock_holders) t
CONNECT BY PRIOR waiting_session = holding_session
START WITH holding_session IS NULL;
4.2.会话、进程、请求
4.2.1.如何查本身的SID
--检查自己的SID
SELECT sid FROM v$session WHERE sid = (SELECT sid FROM v$mystat WHERE rownum =
1);
4.2.2.几个ID之间的关系
--SID、SPID、PID
SELECT s.sid session_id, p.spid os_process_id, p.pid oracle_process_id
FROM v$process p, v$session s
WHERE p.addr = s.paddr;
4.2.3.杀死Session和进程
--杀死Session和进程
SELECT s.sid session_id,
p.spid os_process_id,
p.pid oracle_process_id,
'alter system kill session ''' || to_char(s.sid) || ',' ||
to_char(s.serial#) || ''' immediate;' kill_db_session,
'kill -9 ' || p.spid kill_os_session
FROM v$process p, v$session s
WHERE p.addr = s.paddr
AND s.sid = &sid;
4.2.4.Session正在执行的SQL
--正在执行的SQL
SELECT sql_text
FROM v$sqltext_with_newlines sqlt, v$session s
WHERE sqlt.address = s.sql_address
AND sqlt.hash_value = s.sql_hash_value
AND s.sid = &session_id
ORDER BY piece
4.2.
5.当前引用对象的Session
--引用对象的Session
SELECT acc.*,
'alter system kill session ''' || to_char(ses.sid) || ',' ||
to_char(ses.serial#) ||
''' immediate'
FROM v$access acc, v$session ses
WHERE acc.OBJECT LIKE upper('LOCK_TEST%')
AND acc.sid = ses.sid;
4.2.6.并发请求的Session和SQL
--请求的Session和SQL
SELECT to_char(s.sid) || ',' || to_char(s.serial#), sql_text
FROM applsys.fnd_concurrent_requests r, v$process p, v$session s,
v$sqltext_with_newlines sqlt
WHERE r.oracle_process_id = p.spid
AND p.addr = s.paddr(+)
AND s.sql_address = sqlt.address(+)
AND s.sql_hash_value = sqlt.hash_value(+) AND r.request_id = &request_id
ORDER BY piece;
5.自带的Application Server
对于一些简单的应用或者练习,可以使用Oracle DB自带的Application Server,完成
HTTP应用、Servlets应用、JSP应用、EJB应用、SQLJ应用。
5.1.OC4J概述
以Oracle DB 10.2.0.1.0为例,其OC4J Standalone版本是9.0.4.1.0,兼容J2EE 1.3。
5.1.1.应用范围
1、适用于轻量级、Small-Medium级别的应用
2、支持Java Mail1.1.2、JSP1.2、Servlets2.
3、EJB2.0、JTA1.0、JMS1.0、JNDI1.2、
JDBC2.0E、JAXP1.1、JCA1.0;支持HTTPS,而不需要专门的HTTP服务器
3、支持Oracle Application Server Java Authentication and Authorization Service 1.0
4、不支持负载均衡、集群、OEM;只能是单实例、单JVM、单Server
5.1.2.启动和管理
先设置环境变量到安装目录的oc4j\j2ee\home,如
set J2EE_HOME=D:\Software\Oracle\product\10.2.0\db_1\oc4j\j2ee\home
1、检查配置,在安装目录的%J2EE_HOME%\config\server.xml
进一步查看HTTP服务配置http-web-site.xml,默认端口号是8888
2、启动OC4J命令如下
java -jar %J2EE_HOME%\oc4j.jar -config %J2EE_HOME%\config\server.xml
提示:java -jar %J2EE_HOME%\oc4j.jar -?可以查看帮助
3、
4、启用OC4J管理,执行如下命令,设置管理员admin的密码,如admin
java -jar %J2EE_HOME%\oc4j.jar -config %J2EE_HOME%\config\server.xml –
install
5、OC4J的管理,使用admin.jar,并且通过ORMI协议,配置文件为rmi.xml,默认端
口号是23791。查看命令:
java -jar %J2EE_HOME%\admin.jar ormi://huajhua:23791 admin admin -?
关闭服务shutdown
重启服务restart
发布应用deploy
删除应用undeploy
配置Site site
绑定App到Site bindWebApp
查看App信息application
检查/载入配置updateConfig
5.2.配置和发布
5.2.1.server.xml,OC4J Instance配置文件
(container级别的除外)、自动发布ear文件。
增加应用需要在这里增加一组配置。
5.2.2.principals.xml,OC4J安全性配置文件
配置组、用户和密码。
5.2.3.application.xml
应用配置,除了全局的application.xml,每个应用都有自己的application.xml。
5.2.4.data-sources.xml,数据库配置信息
简单的应用可以直接使用默认的数据源OracleDS,修改下username、password、url
参数即可。需要在application.xml指定data-sources的路径。
5.2.5.*web-site.xml
http-web-site.xml是全局Site,端口在这里配置。
5.2.
6.jazn.xml
Oracle Application Server Java Authentication and Authorization Service的用户认证
文件,密码是加密的。
5.2.7.最简单的jsp发布
把class文件和jsp文件放入%J2EE_HOME%\default-web-app目录即可。
访问实例:http://huajhua:8888/HelloWorld.jsp
5.2.8.最简单的servlet发布
把class文件放入%J2EE_HOME%\default-web-app\WEB-INF\classes目录即可。
访问实例:http://huajhua:8888/servlet/HelloWorldServlet
5.2.9.完整的J2EE应用发布
1、打包成EAR文件,目录结构如下(META-INF/WEB-INF/XML文件名都不能改)
appname
META-INF
application.xml
EJB classes
META-INF
ejb-jar.xml
index.html
JSP pages
WEB-INF
web.xml
classes
Servlet classes
lib
dependent libraries
Client classes
META-INF
application-client.xml
2、放入%J2EE_HOME%\applications目录,使用admin.jar发布或者手工修改
server.xml增加***-web-site.xml文件发布
3、如果需要连接数据库,则配置下data-sources.xml
5.2.10.完整的J2EE应用发布示例
1、下载示例应用,并解压
https://www.doczj.com/doc/3313904344.html,/technology/tech/java/oc4j/demos/904/FAQApp/OC4JF AQApp.zip
2、创建数据库用户FAQ/FAQ
create user faq
identified by faq;
grant connect,resource to faq;
3、用FAQ登录数据库,用CreateTables.sql创建数据库对象
4、修改%J2EE_HOME%\config\data-sources.xml,使用默认的OracleDS,所以仅修
改:
username="faq"
password="faq"
url="jdbc:oracle:thin:@huajhua:1522:orcl"
5、使用JAZN认证,增加用户命令如下(失败)
> java -jar jazn.jar -adduser https://www.doczj.com/doc/3313904344.html,
> java -jar jazn.jar -grantrole users https://www.doczj.com/doc/3313904344.html,
6、把FAQApp.ear拷贝到%J2EE_HOME%\applications
7、须改server.xml,在
8、修改http-web-site.xml,增加
FAQApp,如果没有,就重启
10、把%J2EE_HOME%\jsp\lib\taglib\下的所有文件拷贝
到%J2EE_HOME%\applications\FAQApp\FAQAppWeb\WEB-INF\lib 11、访问:http://huajhua:8888/FAQApp