方法一:在并发程序定义界面将并发程序定义成互斥的,但是该种互斥方法是全局的,也就是说任何情况下该请求同一时间都只能跑一个,这样的话有些业务就不能满足了,比如只要求在同一个OU下不能并发,定义界面如下:
方法二:使用DBMS_LOCK这个标准包,该方法非常灵活,几乎可以满足所有的业务需求,但是该方法只能在有apps权限的情况下使用,所有如果当权限不足是则不适用了,下面就以同一个OU下不能并发为例,做个小例子:
DECLARE
-- lock
l_lockname VARCHAR2(100);
l_lockhandle VARCHAR2(200);
l_lock_output NUMBER;
l_locked BOOLEAN := FALSE;
g_pkg_name VARCHAR2(240) := 'test_package';
g_org_id NUMBER := 125;
BEGIN
/* 定义按何种方式并发(此处为同一个OU不能同时执行)
* lockname类似于定义一个唯一的名字,当并发程序执行时就会去判断是否这个唯一标识已经存在*/
l_lockname := g_pkg_name || '_' || g_org_id;
--根据l_lockname获取唯一标识l_lockhandle
dbms_lock.allocate_unique(lockname => l_lockname,
lockhandle => l_lockhandle);
/*用l_lockhandle这个唯一标识去给当前请求加锁
-- Return value:
-- 0 - success
-- 1 - timeout
-- 2 - deadlock
-- 3 - parameter error
-- 4 - already own lock specified by 'id' or 'lockhandle'
-- 5 - illegal lockhandle*/
l_lock_output := dbms_lock.request(l_lockhandle,
6,
60,
FALSE);
IF l_lock_output <> 0 THEN
--Output lock failure message
RAISE apps.fnd_api.g_exc_error;
END IF;
--此处添加请求的业务逻辑
--dbms_lock.sleep(seconds => 50);
/*特别注意的是一定要将lockname释放掉 否则这个并发就永远别想再执行了*/
IF l_lock_output = 0 THEN
l_lock_output := dbms_lock.release(l_lockhandle);
END IF;
EXCEPTION
WHEN apps.fnd_api.g_exc_error THEN
IF l_lock_output = 0 THEN
l_lock_output := dbms_lock.release(l_lockhandle);
END IF;
WHEN OTHERS THEN
IF l_lock_output = 0 THEN
l_lock_output := dbms_lock.release(l_lockhandle);
END IF;
END;
方法三:在相应业务条件下查询当前是否有正在运行的请求,如果有则退出或等待,该方法一定要根据实际业务情况来判断是否能使用,还是以同一个OU下不能并发为例:
SELECT COUNT(1)
INTO l_count_request
FROM apps.fnd_concurrent_programs fcp,
apps.fnd_concurrent_requests fcr
WHERE 1 = 1
AND fcp.application_id = fcr.program_application_id
AND fcp.concurrent_program_id = fcr.concurrent_program_id
AND fcp.concurrent_program_name = 'CUXTEST'
AND fcr.request_id <> apps.fnd_global.conc_request_id
AND fcr.argument1 = p_org_id
AND fcr.phase_code = 'R';
IF l_count_request > 0 THEN
RAISE apps.fnd_api.g_exc_error;
END IF;