关于在SpringMVC框架中 实现数据库session会话环境变量的功能

前言:
由于SpringMVC框架对于数据库会话处理方面,实现了会话池的功能,以提高数据库的工作效率。因为在数据库申请一个新的会话session确实是比较耗资源。
问题:
但是,这样子,session被公用就带来一个新的问题:数据库的session级的环境变量就可能不可以直接使用了。
首先我们要理解,为什么要用数据库的session的环境变量?用过OracleEBS开发的人都知道,数据库的session环境变量是相互隔离的:不同的session,session级的环境变量不同。举个例子,用户A登录用一个session,可以在session级添加一个环境变量:用户是A。然后,这个会话的所有的DML修改,获取新增人或者更新用户的时候,都可以自动抓到该session的环境变量即可。
可以大大提高开发的工作效率。
但是,由于SpringMVC框架的原因,在jdbc调用数据库的时候,可能session被公用。这样子就很可能出现张冠李戴的问题了。
问题解决:
这个问题也困扰了一点时间。
最后我的解决办法是:
在Service层添加一个AOP初始化对应的会话的环境变量。切面所有的Service的代码,在代码执行之前,先重新初始化该session的环境变量,即可。
需要注意的是,这样子做必须要注意2个问题:
1 Service层必须是启用Transaction事务处理的。因为启用了事务处理,service在调用数据库session的时候,才可以线程安全。经过测试,如果一个事务没执行完毕;另外一个新的sql要做事务的时候,是自动调用一个新的数据库session的!
2 需要注意SpringMVC框架的单例模式而带来的安全性的问题。
最简单初始化环境变量的ID是通过参数,从controller层传到Service层。这样子就没风险了。然后AOP可以直接监控到对应的ID,再自动初始化环境变量。但是,这个办法有一个致命的缺点:就是必须为每个方法添加参数。对于大型系统来说简直是噩梦,要改N个功能。
所以,我用的是另外一个办法:用java.lang.ThreadLocal技术提供线程安全。然后,在AOP运行的时候,可以自动获取到对应的初始化环境变量的ID信息,进行初始化。
具体步骤:
在Controller层,抓取session对应的环境变量ID,对service层进行初始化:

UVS.setLoginId((Long)sess.getAttribute("LOGIN_ID"));

对应的,在Service层添加ThreadLocal技术的成员变量:

    private ThreadLocal<Long> loginIdTL = new ThreadLocal<Long>();

    public Long getLoginId() {
        return this.loginIdTL.get();
    }

    public void setLoginId(Long loginId) {
        this.loginIdTL.set(loginId); 
    }

最后,写一个AOP,切所有的service层的代码,进行环境变量的自动初始化:

    /*** 
     * service层调用之前先自动初始化环境变量
     * @throws Exception 
     */  
    @Before("execution(* com.xinyiglass.springSample.service..*.*(..))")  
    public void alb2bInit(JoinPoint joinPoint) throws Exception{
        Method method = null;
        Object target = null;
        Long loginId=null;
        String methodName = "getLoginId";
        target = joinPoint.getTarget();
        method = getMethodByClassAndName(target.getClass(), methodName);
        if(method!=null){
            loginId=(Long) method.invoke(target);//LogUtil.log("loginId:"+loginId);
            if(loginId!=null&&loginId>0&&loginId!=utilDao.getLoginId()){
                PlsqlRetValue ret =utilDao.alb2bInit(loginId);//初始化环境变量!
                if(ret!=null&&!TypeConvert.isNullValue(ret.getErrbuf())) LogUtil.log("ret:"+ret.toJsonStr());
            }
        }
    }    

完工!

后语:
必须要理解几个知识点。
特别是关于Spring单例模式导致其层的全局变量的问题:
http://blog.sina.com.cn/s/blog_12bf601660102uwq2.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC框架实现数据库查询可以通过以下步骤进行: 1. 配置数据库连接:在Spring的配置文件(如applicationContext.xml),配置数据库连接信息,包括数据库驱动、URL、用户名和密码等。 2. 创建数据访问对象(DAO):创建一个DAO接口,并在其实现编写数据库查询的相关代码。可以使用Spring提供的JdbcTemplate来简化数据库操作,或者使用其他ORM框架如MyBatis。 3. 配置数据源和事务管理:在配置文件配置数据源和事务管理器,以确保数据库连接的正确获取和事务的管理。 4. 创建控制器(Controller):创建一个控制器类,用于处理前端请求并调用DAO层的方法来进行数据库查询操作。 5. 定义请求映射:使用Spring MVC的注解或配置文件,将前端请求映射到相应的控制器方法。 6. 编写前端页面:根据需要,编写前端页面来显示查询结果。可以使用JSP、Thymeleaf等模板引擎来渲染页面。 以下是一个简单的示例代码来演示在Spring MVC实现数据库查询: ```java // DAO接口 public interface UserDao { public List<User> getUsers(); } // DAO实现类 public class UserDaoImpl implements UserDao { private JdbcTemplate jdbcTemplate; // 注入JdbcTemplate对象 public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<User> getUsers() { String sql = "SELECT * FROM users"; List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper(User.class)); return users; } } // 控制器类 @Controller public class UserController { @Autowired private UserDao userDao; @RequestMapping("/users") public String getUsers(Model model) { List<User> users = userDao.getUsers(); model.addAttribute("users", users); return "userList"; } } // 前端页面(userList.jsp) <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>User List</title> </head> <body> <h1>User List</h1> <table> <tr> <th>ID</th> <th>Name</th> </tr> <c:forEach items="${users}" var="user"> <tr> <td>${user.id}</td> <td>${user.name}</td> </tr> </c:forEach> </table> </body> </html> ``` 以上是一个简单的例子,根据实际需求,你可以根据Spring MVC的特性进行更加复杂的数据库查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值