编写java web的dao类,该类能不能有成员变量?
编写javaweb时的dao类,(比如OperateDao)该类能不能有成员变量?比如privateConnectioncon=null之类的;因为我在一个Servlet...
编写java web时的dao类,(比如OperateDao)该类能不能有成员变量?比如private Connection con = null之类的;
因为我在一个Servlet中只创建了一个该类的局部实例,调用该类的方法,这时候考虑到线程的问题,不知道能不能有成员变量 展开
因为我在一个Servlet中只创建了一个该类的局部实例,调用该类的方法,这时候考虑到线程的问题,不知道能不能有成员变量 展开
展开全部
以前我也和你有过同样的困惑,仔细分析一下,什么时候会有线程安全问题呢?当多个线程并发修改和读取某个变量时就会发生。
一般的dao类,被容器或框架实现成了一个单例,而web程序明显是多线程的,所以在没有任何防范措施的情况下给dao声明属性变量,可能会造成线程安全问题,同理,service层也存在这样的问题。
如何才能让dao拥有属性变量,又不会造成线程安全问题呢?我所了解的有几种策略,但都存在各自的问题:
1. 最省心的办法是使用ThreadLocal类,但是在线程池环境下需要小心地设置和删除ThreadLocal线程局部变量,以保证不同用户线程之间数据的正确性和隐私;
2. 可以对每个涉及到的方法加锁,线程同步等待获得锁会带来大把的性能损失;
3. 也可以将属性声明成volatile的,不过在某些情况下并不总是线程安全的。
顺便说一句,spring代理的DataSource实际上也是通过ThreadLocal来存取Connection的,这样即保证了每个请求的数据独立性,又实现了在一次请求中跨类跨方法的进行事务管理。
综上所述,线程问题会给你带来无穷无尽的烦恼,所以能不在dao里做这样的事最好,方法内部的局部变量是最安全的,或者每次使用都重新new一个对象出来,单例对象是邪恶的,我们没必要为了节省那一点点可怜的内存被搞得焦头烂额的。
一般的dao类,被容器或框架实现成了一个单例,而web程序明显是多线程的,所以在没有任何防范措施的情况下给dao声明属性变量,可能会造成线程安全问题,同理,service层也存在这样的问题。
如何才能让dao拥有属性变量,又不会造成线程安全问题呢?我所了解的有几种策略,但都存在各自的问题:
1. 最省心的办法是使用ThreadLocal类,但是在线程池环境下需要小心地设置和删除ThreadLocal线程局部变量,以保证不同用户线程之间数据的正确性和隐私;
2. 可以对每个涉及到的方法加锁,线程同步等待获得锁会带来大把的性能损失;
3. 也可以将属性声明成volatile的,不过在某些情况下并不总是线程安全的。
顺便说一句,spring代理的DataSource实际上也是通过ThreadLocal来存取Connection的,这样即保证了每个请求的数据独立性,又实现了在一次请求中跨类跨方法的进行事务管理。
综上所述,线程问题会给你带来无穷无尽的烦恼,所以能不在dao里做这样的事最好,方法内部的局部变量是最安全的,或者每次使用都重新new一个对象出来,单例对象是邪恶的,我们没必要为了节省那一点点可怜的内存被搞得焦头烂额的。
追问
首先感谢您给出我这么详细的答案,还有一点不太明白。
您说到“方法内部的局部变量是最安全的,或者每次使用都重新new一个对象出来”,后半句话说道每次都new出一个新对象也可以,请问如果我的方法没有设为同步的,那么这时候使用该成员变量,尽管new出新对象,但还是安全的吗?并且为什么局部变量最安全呢?调用Dao类的Servlet并没有将其进行加锁呀
追答
你的意思是不是说:声明一个成员变量,但在方法内部每次都new一个它的实例?
这种情况还是会有安全问题,因为线程调度是由系统控制的,你不知道它什么时候会发生。举个例子:
private User user;
public void save() {
user = new User();
user.setName("li");
user.setAge(25); // 1
entityManager.persist(user);
}
public void update(String id) {
user = entityManager.find(id);
user.setName("wang");
user.setAge(20); // 2
entityManager.merge(user);
}
现在有2个线程A和B,首先A执行save方法,执行到注释1处线程调度使A暂时挂起,B线程开始执行update方法,执行到2处,调度使B挂起,A重新获得CPU,但这个时候user已经被B线程改变了,但A并不知道这件事,继续执行持久化操作,出现错误!
方法内的局部变量肯定是线程安全的,原因在于每一次的方法调用都会在堆栈上分配存储方法局部变量的空间,由运行时系统保证不同调用之间创建的局部变量是互相隔离的。
参考资料: http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
展开全部
这是什么用法啊?仅使用JDBC连接数据库吗?一般使用框架的话datasource都是已经注入好的。
任何类都可以有属性,只在于你怎么用。这个con对象你可以声明为一个static类变量,仅初始化一次,这样每次调用这个dao时都使用这一个连接,避免经常创建连接DB的操作。
任何类都可以有属性,只在于你怎么用。这个con对象你可以声明为一个static类变量,仅初始化一次,这样每次调用这个dao时都使用这一个连接,避免经常创建连接DB的操作。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
dao类一般只有方法,不过你要一个这样的变量的话,你写个方法,让它返回一个Connection的对象不就行了吗?
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询