Hibernate的Session什么时候关闭最好?

fatso1984 2009-07-07 12:15:51
假设从A表中读出所有数据,在在Hibernate的映射文件中A中包含B
映射文件中默认lazy="true"未改变.这时候如果查询后把Session关闭.当查处的数据被调用的时候调用到A中包含的B对象的时候就会出错.
如果把lazy="false"或者不关闭Session就没问题.
我的做法是等到数据用不到的时候再将Session关闭.
但是有的人说Session不关闭会占用资源而lazy="false"如果是大数据量会降低查询速度.
请问有什么更好的办法么?
谢谢
...全文
4137 51 打赏 收藏 转发到动态 举报
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
金兄 2011-08-03
  • 打赏
  • 举报
回复
[Quote=引用 49 楼 zhengwei223 的回复:]

在web应用中
从SessionFactory获取Session时可以把它放在ThreadLocal里面
这样可以不用管Session的关闭
服务器一般采用一个请求一个线程的方式,意味着只要还是一个请求你拿到的Session是同一个
服务器响应请求的时候会关闭线程
ThreadLocal中的变量将会自动剥离
Java code

private static final Threa……
[/Quote]
我想问一下,这样还用自己手动写 session.set(null),s.close(); 吗? 如果要写的话放在哪里最合适?
小9 2010-10-08
  • 打赏
  • 举报
回复
在web应用中
从SessionFactory获取Session时可以把它放在ThreadLocal里面
这样可以不用管Session的关闭
服务器一般采用一个请求一个线程的方式,意味着只要还是一个请求你拿到的Session是同一个
服务器响应请求的时候会关闭线程
ThreadLocal中的变量将会自动剥离

private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();

if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
//如果当前线程中没有session,开启一个session,并把它与当前线程关联
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}

return session;
}
山城忙碌人 2010-10-05
  • 打赏
  • 举报
回复
留名以后看。
becomewangpan 2010-08-20
  • 打赏
  • 举报
回复
这个帖子还真是火呀.我也遇到了跟session有关的问题:
我就是往数据库里插入记录,前几条还没事,但是后来就出现了问题了
点添加等好长时间然后就出错了
我怀疑是session占用的过多没有释放,而没有可用的session资源了
不知道这个问题怎么解决 ?
晴天v1 2009-08-13
  • 打赏
  • 举报
回复
很好的帖子,学习中。
jeff2033333 2009-07-14
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 LoginOut 的回复:]
引用 37 楼 jeff2033333 的回复:

RuntimeException 是自动回滚,普通Exception需要你自己在catch里面回滚。比如,有的时候异常是transaction活动期间的其它非数据库操作引起的,但由于某方面的考虑,需要回滚该transaction内的所有数据库操作,这个时候“可能”需要你手动回滚。


catch(RuntimeException  e){
session.getTransaction().rollback
e.printStackTrace();
}

也就是说在catch里面手动回滚是最保险的操作…
[/Quote]

说是这么说,谁也都知道,荷包里的钞票要自己亲手数过的才放心,可是你也看到,银行柜台数大票往往还要借助于点钞机,为啥呢,因为人是动物啊,同一个机械动作做久了,你的故障率比机器可高多了。

Hibernate实现自动回滚也是这个道理啊,一般情况下我们不用去管了,我们有限的精力应该放在特别不敢放心的地方,在那里手动控制回滚。
sky_hebiao 2009-07-14
  • 打赏
  • 举报
回复
都厉害
lcb521 2009-07-14
  • 打赏
  • 举报
回复
session用了就关闭的好。
VistaKobe 2009-07-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 daisycool 的回复:]
session 还是用完了就关闭的好,否则容易产生很多问题。Hibernate的一对多查询是个很大的问题(其实任何ORM都有这个问题),我的解决方案是lazy=true,需要的时候再访问数据库获取“多”那一端所需要的数据。这样做会增加数据库访问次数,但优点是不浪费资源,减缓系统缓存压力,增加程序速度。毕竟数据库查询的速度比程序快得多,而且当你获得了“一”的时候想查询“多”,通常都是索引范围内的查询,搜索数据数量控制在百或者千…
[/Quote]

同意。
zlx5219 2009-07-13
  • 打赏
  • 举报
回复
提交完事务关闭
LoginOut 2009-07-13
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 jeff2033333 的回复:]

RuntimeException 是自动回滚,普通Exception需要你自己在catch里面回滚。比如,有的时候异常是transaction活动期间的其它非数据库操作引起的,但由于某方面的考虑,需要回滚该transaction内的所有数据库操作,这个时候“可能”需要你手动回滚。
[/Quote]

catch(RuntimeException e){
session.getTransaction().rollback
e.printStackTrace();
}

也就是说在catch里面手动回滚是最保险的操作?



确实是做项目才是最好的方法
lyz0622_1022 2009-07-13
  • 打赏
  • 举报
回复
[Quote=引用 38 楼 jeff2033333 的回复:]
33楼,万万不敢自称高手,我接触Hibernate也就两星期,项目需要而已。
PS:学习框架,直接做项目才是王道。框架其实都不难的,难的话还用它做什么呢,框架的目的就是让工作变得简单。不过最难的是没有机会用在项目里,毕竟大多数时候项目要用到什么技术、框架,都是老板说了算而不是你。
[/Quote]


还是老板说了算啊
jeff2033333 2009-07-12
  • 打赏
  • 举报
回复
33楼,万万不敢自称高手,我接触Hibernate也就两星期,项目需要而已。
PS:学习框架,直接做项目才是王道。框架其实都不难的,难的话还用它做什么呢,框架的目的就是让工作变得简单。不过最难的是没有机会用在项目里,毕竟大多数时候项目要用到什么技术、框架,都是老板说了算而不是你。
jeff2033333 2009-07-12
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 LoginOut 的回复:]
public void save(Ouser user) {
Session session=HibernateSessionFactory.getSessionFactory().getCurrentSession();
try{
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}catch(RuntimeException  e){
//session.getTransaction().rollback 自动个还是需手动
e.printStackTrace();
}
}
[/code]

默认情况下Hibernate只有遇到运行时异常,数据库操作才会回滚,普通异常不会回滚
那么这个回滚是自动回滚吗?还是说需要手动回滚
[/Quote]

RuntimeException 是自动回滚,普通Exception需要你自己在catch里面回滚。比如,有的时候异常是transaction活动期间的其它非数据库操作引起的,但由于某方面的考虑,需要回滚该transaction内的所有数据库操作,这个时候“可能”需要你手动回滚。
lvfeng19806001 2009-07-11
  • 打赏
  • 举报
回复
我是在过滤器中关闭session的!
meander 2009-07-11
  • 打赏
  • 举报
回复
mark
LoginOut 2009-07-11
  • 打赏
  • 举报
回复
public void save(Ouser user) {
Session session=HibernateSessionFactory.getSessionFactory().getCurrentSession();
try{
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}catch(RuntimeException e){
//session.getTransaction().rollback 自动个还是需手动
e.printStackTrace();
}
}
[/code]

默认情况下Hibernate只有遇到运行时异常,数据库操作才会回滚,普通异常不会回滚
那么这个回滚是自动回滚吗?还是说需要手动回滚
LoginOut 2009-07-11
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 bllizard 的回复:]
30楼啊,我涨见识了
[/Quote]
应该是说 jeff2033333 很强,呵呵

[Quote=引用 30 楼 bllizard 的回复:]
此外,当你使用Hibernate3.2或以后的版本,如无要求对事务执行中抛出的异常进行特殊处理,try catch 甚至都不需要。 Hibernate的回滚原理,是必须RuntimeException以上的异常级别才会自动回滚,如果是普通的Exception则不会回滚,需要程序员手工在catch里面回滚。但Hibernate3.2以后抛出的都是RuntimeException,所以try catch也无必要了。
[/Quote]
也就是所Hibernate3.2后,不用显示的定义事务,和try...catch
怪不得MyEclipse自动生成的Dao里面没有定义事务的声明和回滚,但是有try catch

public void save(Ouser transientInstance) {
log.debug("saving Ouser instance");
try {
getSession().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}

public void delete(Ouser persistentInstance) {
log.debug("deleting Ouser instance");
try {
getSession().delete(persistentInstance);
log.debug("delete successful");
} catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}

LoginOut 2009-07-10
  • 打赏
  • 举报
回复
在深入浅出-Hibernate中5.3.2中有说:

在Filter中获取和关闭Session,并在周期内运行的所有对象(Filter 链中其余的Filter,
及其覆盖的Servlet和其他对象)对此Session的实例进行重用,保证了一个HttpRequest
处理过程中只占用一个Session,提高了整体性能表现


我想请教下,Filter处理Session.close()和21楼的写法比较,优缺点是什么?
bllizard 2009-07-10
  • 打赏
  • 举报
回复
我知道你没有其他的意思,我也是让你明白我的意思
加载更多回复(30)

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧