2019独角兽企业重金招聘Python工程师标准>>>

审计字段即记录数据的创建人、创建时间、修改人、修改时间的字段、体现在每一张数据库表中。为了减少代码量需要设置一套通用的方法。

思路:登录用户存入session,访问数据库的时候拦截器获取链接先设入数据库session,随后进行业务逻辑,每个表设置trigger,每次更新时获取session中的用户名称,设置入审计字段。

1、用户信息Web到App的传递。

思路:拦截分发器,每次分发请求的时候在ServiceRequest中设置用户信息传递到App。

首先设置页面拦截,获取session中的用户信息放入用户线程上下文。

web-context.xml

<bean id="sessionInterceptor" class="com.palic.egis.common.web.util.SessionInterceptor"><description>AuthorizationController用来检查用户是否login</description><property name="worktableAssociatedFilter"><list><value>/index.screen</value></list></property></bean> <bean id="defaultHandlerMapping" class="com.paic.pafa.app.web.servlet.handler.BeanNameUrlHandlerMapping"><description>当一个HTTP请求进来的时候,interceptors先拦截请求,进行预先处理。</description><property name="interceptors"><list><ref local="sessionInterceptor"/></list></property></bean>

common-context.xml

<!--=====================================================================--><!-- 线程context的配置 --><!--=====================================================================--><bean id="userThreadContext"class="com.paic.pafa.core.service.PafaThreadContext"><description>线程的Context</description></bean>

SessionInterceptor.java  拦截器实现

/*** 用于检查Session里是有用户登录信息的拦截器。Interceptor的功能类似于Servlet的Filter。* 当一个HTTP请求进来的时候,interceptors先拦截请求,进行预先处理。* * @author Leo Liao, 2005-4-14, created* @version $Revision$Date$* @see com.palic.egis.support.privilege.web.controller.LoginController*/
public class SessionInterceptor extends HandlerInterceptorAdapter {// 用于获取用户信息的LoginControllerprivate Controller    authorizationController;// 目前SessionAdmin有待完善,请暂时不要使用// private SessionAdmin sessionAdmin;/*** 检查session里是不是有用户信息* * @see com.palic.egis.support.privilege.web.controller.LoginController*/private boolean checkSession(HttpServletRequest request) {HttpSession session = request.getSession();if (session != null && session.getAttribute("currentUser") != null) {return true;}return false;}public final boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws PafaWebException {try {if (!checkSession(request)) {authorizationController.handleRequest(request, response);if (!checkSession(request)) {throw new PafaWebException("appdemo.error.session.invalid");}}// begin 设置当前用户到线程上下文HttpSession session = request.getSession();String uid = (String) session.getAttribute("currentUser");PafaThreadContext tc = (PafaThreadContext) PafaAppCommonContexton.getInstance().getBean(SystemObjectName.USER_THREAD_CONTEXT);tc.putTxnID(PafaCoreContexton.getInstance().getIDGenerator().getID());tc.putUserID(uid);// end} catch (PafaWebException ex) {// throw new PafaWebException("appdemo.error.session.invalid", ex);request.getSession().setAttribute("loginError",ex.getInitialCause().getMessage());} catch (Exception ex) {// throw new PafaWebException("appdemo.error.session.invalid", ex);request.getSession().setAttribute("loginError", ex.getMessage());}return true;}/*** 清除threadContext中设置的用户信息*/public final void afterCompletion(HttpServletRequest httpservletrequest,HttpServletResponse httpservletresponse, Object obj,Exception exception) throws Exception {PafaThreadContext tc = (PafaThreadContext) PafaAppCommonContexton.getInstance().getBean(SystemObjectName.USER_THREAD_CONTEXT);tc.clear();super.afterCompletion(httpservletrequest, httpservletresponse, obj,exception);}}

common-context.xml    分发器配置

<!-- Real pafaAC --><bean id="pafaACTarget"class="com.paic.pafa.app.lwc.service.remoting.access.ejb.SmartRemoteStatelessSessionProxyFactoryBean"><property name="jndiName"><value>ejb/egis/PafaAC</value></property><property name="businessInterface"><value>com.paic.pafa.app.biz.ac.ApplicationController</value></property><property name="jndiTemplate"><ref local="pafaACJndi" /></property></bean><!-- pafaAC Proxy --><bean id="pafaAC"class="com.paic.pafa.app.lwc.core.aop.framework.ProxyFactoryBean"><property name="target"><ref local="pafaACTarget"/></property><property name="proxyInterfaces"><value>com.paic.pafa.app.biz.ac.ApplicationController</value></property><property name="interceptorNames"><list><value>dispatchServiceAdvisor</value></list></property></bean><bean id="dispatchServiceAdvisor"class="com.paic.pafa.app.lwc.core.aop.support.NameMatchMethodPointcutAdvisor"><property name="mappedName"><value>handleRequest</value></property><property name="advice"><ref bean="dispatchServiceInterceptor"/></property>    </bean><bean id="dispatchServiceInterceptor"class="com.palic.egis.common.web.util.ThreadContextInterceptor"><property name="threadContext"><ref bean="userThreadContext"/></property></bean>

ThreadContextInterceptor.java

public class ThreadContextInterceptor implements MethodInterceptor {private PafaThreadContext threadContext = null;public PafaThreadContext getThreadContext() {return threadContext;}public void setThreadContext(PafaThreadContext threadContext) {this.threadContext = threadContext;}public Object invoke(MethodInvocation method) throws Throwable {Object[] args = method.getArguments();ServiceRequest sr = (ServiceRequest) args[0];if (sr != null) {SessionDTO dto = sr.getSessionDTO();if(dto.getUserId() == null){dto.setUserId(threadContext.getUserID());              }if (dto.getTxnId() == null) {dto.setTxnId(threadContext.getTxnID());}}return method.proceed();}

2、APP层传入数据库

思路:拦截数据源,先设置数据库session在执行业务逻辑

biz-context.xml

<bean id="dsFactory"class="com.paic.pafa.app.lwc.service.persistence.datasource.DataSourceFactoryBean" ><property name="defaultDSKey"><description>缺省的数据源,必须指定为下面map中的entry key之一</description><value>GBSDS</value></property><property name="dataSources"><description>可以在map属性里面添加多个数据源</description><map><entry key="GBSDS"><ref local="defaultDS"/></entry><entry key="GBSDS_XA"><ref local="gbsDS_XA"/></entry></map></property></bean><bean id="defaultDS"class="com.paic.pafa.app.lwc.core.aop.framework.ProxyFactoryBean"><property name="target"><ref local="defaultDSTarget" /></property><property name="proxyInterfaces"><value>javax.sql.DataSource</value></property><property name="interceptorNames"><list><value>dbConnectionAdvisor</value></list></property></bean>     <bean id="dbConnectionAdvisor"class="com.paic.pafa.app.lwc.core.aop.support.NameMatchMethodPointcutAdvisor"><property name="mappedName"><value>getConnection</value></property><property name="advice"><ref bean="dbConnectionInterceptor"/></property>    </bean><bean id="dbConnectionInterceptor"class="com.palic.egis.common.util.SetLcuInterceptor"></bean>    <bean id="defaultDSTarget"class="com.paic.pafa.app.lwc.core.naming.JndiObjectFactoryBean"><property name="jndiName"><value>${defaultDS}</value></property><property name="jndiTemplate"><ref local="jndiTemplate"/></property></bean>    <bean id="gbsDS_XA"class="com.paic.pafa.app.lwc.core.naming.JndiObjectFactoryBean"><property name="jndiName"><value>${GBSDS_XA}</value></property><property name="jndiTemplate"><ref local="jndiTemplate"/></property></bean>

SetLcuInterceptor.java

public class SetLcuInterceptor implements MethodInterceptor {public Object invoke(MethodInvocation mi) throws Throwable {String userId = PafaCoreContexton.getInstance().getThreadContext().getUserID();Connection conn = (Connection) mi.proceed();if (userId != null && !userId.startsWith("V_") && !userId.equalsIgnoreCase("GMONIUSER")) {       try {PreparedStatement stat = null;// 设置LCUtry {stat = conn.prepareStatement("{call pub_sys_package.set_attributes(?)}");stat.setString(1, userId);                 stat.execute();} catch (Throwable e) {throw e;} finally {if (stat != null) {stat.close();}}    } catch (Throwable e) {DevLog.error("SetLcuInterceptor Error:" + e.getMessage());    }}return conn;}}

pub_sys_package

CREATE OR REPLACE PACKAGE BODY pub_sys_package IS--get user的两种访问1/proPROCEDURE get_user_p(p_user OUT VARCHAR2) IS  BEGINp_user := get_user;END get_user_p;--get user的两种访问2/funFUNCTION get_user RETURN VARCHAR2 ISv_user VARCHAR2(100);CURSOR cur_empno ISSELECT user_empnoFROM gbs_user--根据登录名称查询WHERE user_name = USER;BEGINSELECT sys_context('user_policy_context', 'uid')INTO v_userFROM dual;IF v_user IS NULL THENOPEN cur_empno;FETCH cur_empnoINTO v_user;CLOSE cur_empno;END IF;IF v_user IS NULL THENv_user := USER;    END IF;RETURN v_user;END get_user;--***********************************************-- 功能说明:--   在获得Connection时调用,用于将用户信息设置到数据库的context中-- 参数说明:--   uid     用户标志-- 调用函数:--   无--***********************************************PROCEDURE set_attributes(uid VARCHAR2) ISregionlist VARCHAR2(100) := NULL;BEGINdbms_session.set_context('user_policy_context', 'logon', 'true');dbms_session.set_context('user_policy_context', 'uid', uid);END set_attributes;--***********************************************-- 功能说明:--   在获得Connection时调用,用于将用户信息设置到数据库的context中。egis-pos专用--   在lcu长度不够的时代,保全利用该过程传入full_uid,记录在另外的字段中-- 参数说明:--   uid     用户标志-- 调用函数:--   无--***********************************************PROCEDURE set_attributes(uid VARCHAR2, full_uid VARCHAR2) ISregionlist VARCHAR2(100) := NULL;BEGINdbms_session.set_context('user_policy_context', 'logon', 'true');dbms_session.set_context('user_policy_context', 'uid', uid);dbms_session.set_context('user_policy_context', 'full_uid', full_uid);END set_attributes;--***********************************************-- 功能说明:--   数据库集中:将从UM中获取的region信息set到context中-- 参数说明:--   uid            用户名--   access_region  可访问的region列表,以,分隔-- 调用函数:--   无--***********************************************PROCEDURE set_access_attributes(uid VARCHAR2, access_region VARCHAR2) ISBEGINdbms_session.set_context('user_policy_context', 'logon', 'true');dbms_session.set_context('user_policy_context', 'uid', uid);dbms_session.set_context('user_policy_context','access_region',access_region);END set_access_attributes;FUNCTION get_fcu(infcu IN VARCHAR2) RETURN VARCHAR2 ISv_fcu VARCHAR2(100);  v_user_empno VARCHAR2(100);BEGINv_user_empno := pub_sys_package.get_user;IF v_user_empno = 'SOLIX' THEN--如果是归档用户,则使用原有记录的数据 v_fcu := infcu;     ELSE    v_fcu := v_user_empno;    END IF;RETURN v_fcu;END;FUNCTION get_fcd(infcd IN VARCHAR2) RETURN DATE ISv_fcd DATE;    v_user_empno VARCHAR2(100);  BEGINv_user_empno := pub_sys_package.get_user;  IF v_user_empno = 'SOLIX' THEN--如果是归档用户,则使用原有记录的数据v_fcd := infcd;     ELSE    v_fcd := SYSDATE;    END IF;RETURN v_fcd;END;FUNCTION get_lcu(inlcu IN VARCHAR2) RETURN VARCHAR2 ISv_lcu VARCHAR2(100);BEGINv_lcu := pub_sys_package.get_user;IF v_lcu IS NULL THENv_lcu := inlcu;end IF;RETURN v_lcu;END;FUNCTION get_lcd(inlcd IN VARCHAR2) RETURN DATE ISv_lcd DATE;BEGIN    v_lcd := SYSDATE;RETURN v_lcd;END;END pub_sys_package;

数据库表中trigger实例:

插入

create or replace trigger TR_I_table_name
before insert on table_name
for each row
declare--通用变量定义v_trigger_user varchar2(100);v_trigger_date date;v_sqlcode varchar2(6);v_sqlerrm varchar2(200);v_error_comment varchar2(300);--针对审计字段更新功能定义的游标和变量cursor c_switch(cp_switch gbs_tr_switch.switch_for%type) isselect status from gbs_tr_switchwhere trigger_name='TR_I_table_name' and switch_for =cp_switch;v_status gbs_tr_switch.status%type;beginv_error_comment:='before get user';v_trigger_user :=pub_sys_package.get_user;v_trigger_date :=sysdate;--需求来源:表中记录的审计字段信息更新--功能描述:用于保证审计信息的完整性v_error_comment:='before GBS_insert_4_audit_column';open c_switch('table_name_in');fetch c_switch into v_status;if c_switch%found and v_status ='1' then:new.created_by:=v_trigger_user;:new.created_date:=v_trigger_date;:new.updated_by:=v_trigger_user;:new.updated_date:=v_trigger_date;end if;close c_switch;--需球来源:XXXX--功能描述:XXXX--错误处理--触发器执行有误,将出错信息插入到gbs_tr_error_log表exceptionwhen others thenv_sqlcode :=sqlcode;v_sqlerrm :=substr(sqlerrm,1,200);insert into  gbs_tr_error_log(error_no ,         --系统错误代码error_message ,    --系统错误信息trigger_name ,     --出错的triggertrigger_user ,     --出错的用户trigger_date ,     --出错的时间error_comment      --出错详细信息)values(v_sqlcode,v_sqlerrm,'TR_I_table_name',v_trigger_user,v_trigger_date,v_error_comment);
end;

更新

CREATE OR REPLACE TRIGGER tr_u_table_nameBEFORE UPDATE ON table_nameFOR EACH ROW
DECLARE--通用变量定义v_trigger_user  VARCHAR2(100);v_trigger_date  DATE;v_sqlcode       VARCHAR2(6);v_sqlerrm       VARCHAR2(200);v_error_comment VARCHAR2(300);--针对审计字段更新功能定义的游标和变量CURSOR c_switch(cp_switch gbs_tr_switch.switch_for%TYPE) ISSELECT statusFROM gbs_tr_switchWHERE trigger_name = 'tr_u_table_name'AND switch_for = cp_switch;v_status gbs_tr_switch.status%TYPE;BEGINv_error_comment := 'before get user';v_trigger_user  := pub_sys_package.get_user;v_trigger_date  := SYSDATE;--需求来源:表中记录的审计字段信息更新--功能描述:用于保证审计信息的完整性v_error_comment := 'before GBS_update_2_audit_column';OPEN c_switch('table_name_up');FETCH c_switchINTO v_status;IF c_switch%FOUNDAND v_status = '1' THEN:new.updated_by   := v_trigger_user;:new.updated_date := v_trigger_date;END IF;CLOSE c_switch;EXCEPTIONWHEN OTHERS THENv_sqlcode := SQLCODE;v_sqlerrm := substr(SQLERRM, 1, 200);INSERT INTO tr_error_log(error_no, --系统错误代码error_message, --系统错误信息trigger_name, --出错的triggertrigger_user, --出错的用户trigger_date, --出错的时间error_comment --出错详细信息)VALUES(v_sqlcode,v_sqlerrm,'tr_u_table_name',v_trigger_user,v_trigger_date,v_error_comment);
END;

转载于:https://my.oschina.net/kanlianhui/blog/223801

Oracle 业务表自制审计字段使用相关推荐

  1. MySql 、Oracle 获取表结构和字段信息

    MySql获取表结构信息 SELECTTABLE_NAME,TABLE_COMMENT FROMinformation_schema.`TABLES` WHERETABLE_SCHEMA = 'dm' ...

  2. oracle删除表的一个字段的数据库,学会Oracle数据库删除表字段和Oracle数据库表增加字段方法...

    Oracle数据库添加字段的语法:alter table tablename add (column datatype [default  value][null/not null],-.); Ora ...

  3. oracle 将表名和字段名变为大写

    文章目录 前言 一.批量将表名变为大写 二.批量将空间内所有表的所有字段名变成大写 三.将用户空间的所有表名及所有字段变为大写 前言 当使用powerdesigner创建数据库时要注意大小写. 注:以 ...

  4. oracle多表关联多字段update

    多表关联多字段update 有代码有J8: update spatial_references set( auth_name, auth_srid, falsex, falsey, xyunits, ...

  5. oracle在表中增加字段

    alter  table 表名  add (字段名 字段类型(字段长度),字段名 字段类型(字段长度)); 例如:alter  table students  add (starttime varch ...

  6. oracle删除表某一字段,oracle中删除表中某字段出现重复的信息 保留其中一条

    记得以前有个同事问过我这个,说是以前面试的时候碰到的问题,下面我介绍三种方法. 首先我们在这里创建一个测试表添加相应的测试数据. create table test  (id number,name ...

  7. oracle查看表有某字段类型,oracle查看某表字段类型

    来源:https://www.cnblogs.com/ufindme/p/5033843.html 今天遇到一个问题:要求在可重复执行的SQL脚本添加一段SQL代码:修改当前的数据类型.因为SQL代码 ...

  8. Oracle创建表以及添加字段备注

    目录 (一)检测插入信息的时候必须制定的字段 (二)设置主键以及非空 (三)创建表 (四)给表添加备注 (五)查询备注 (六)查看表备注 (七)创建同义词以及授予增删改查权限 1.创建序列: 2.查询 ...

  9. oracle修改表某列字段长度

    1.修改一个列 alter table 表名 modify name varchar2(60); 2.修改多个列 alter table 表名 modify (name varchar(60),nam ...

最新文章

  1. mysql $lt_MongoDB与Mysql常用命令解释
  2. 小甲鱼 OllyDbg 教程系列 (八) :fjproducer 逆向 之 困境
  3. Ajax的简单使用方法
  4. 微信公众号“成为开发者”实践代码
  5. nginx反向代理解决跨域
  6. IE6不支持position:fixed解决方法
  7. iconfont 阿里巴巴矢量图标库 在线引入图标
  8. 微型计算机控制技术第二版第六章课后答案,微型计算机控制技术第6章习题答案...
  9. 【dubbo源码解析】--- dubbo的服务暴露+服务消费(RPC调用)底层原理深入探析
  10. 论文笔记(1) B4: Experience with a Globally-Deployed Software Defined WAN
  11. Mac电脑怎么设置动态桌面,heic动态桌面壁纸怎么使用
  12. 《数字图像处理》题库1:选择题
  13. 腾讯和360之争所折射出的下作
  14. python笔记3 闭包 装饰器 迭代器 生成器 内置函数 初识递归 列表推导式 字典推导式...
  15. mysql查看表内容_在mysql中怎样显示表里的内容 ?
  16. 三维重建 几何方法 深度学习_基于深度学习的三维重建算法综述
  17. PHP初级程序员出路
  18. UML系列——时序图(顺序图)
  19. 评论:雨林木风Linux 意义和目的是什么?
  20. java 过期注解_JDK新特性-----注解@ (@Override、@Deprecated、@SuppressWarings)

热门文章

  1. WebRTC -- 官方apprtc示例搭建
  2. 胎儿超声标准切面 图与详解
  3. T(n) = 25T(n/5)+n^2的时间复杂度(转)
  4. 互联网入侵教育培训业 在线教育优势弊端在哪?
  5. JAVA基础知识(用已知,释新知道)
  6. 【华为OD】【003-求N阶方阵的和】
  7. python小游戏扫雷怎么玩的技巧_用 Python 实现扫雷小游戏
  8. 从滴滴到AirBnB,交易平台战争的秘密
  9. 微信春节大数据出炉:《三体》阅读量第一 ;曝iOS 17应用商店将向第三方开放;斯坦福大学推出DetectGPT|极客头条
  10. 十步法原则解决数据质量问题