假设从A表中读出所有数据,在在Hibernate的映射文件中A中包含B
映射文件中默认lazy="true"未改变.这时候如果查询后把Session关闭.当查处的数据被调用的时候调用到A中包含的B对象的时候就会出错.
如果把lazy="false"或者不关闭Session就没问题.
我的做法是等到数据用不到的时候再将Session关闭.
但是有的人说Session不关闭会占用资源而lazy="false"如果是大数据量会降低查询速度.
请问有什么更好的办法么?
谢谢
映射文件中默认lazy="true"未改变.这时候如果查询后把Session关闭.当查处的数据被调用的时候调用到A中包含的B对象的时候就会出错.
如果把lazy="false"或者不关闭Session就没问题.
我的做法是等到数据用不到的时候再将Session关闭.
但是有的人说Session不关闭会占用资源而lazy="false"如果是大数据量会降低查询速度.
请问有什么更好的办法么?
谢谢
但是如果设置成lazy=false 的话没问题了.貌似当你调用B的时候它会再次发出查询..就是这里困扰了我很久
借鉴一下大家以往的经验
在网上找了找,有人说是用Fitler 来控制Session.close()
而有的人说是用完了就关
# FilterChain chain) throws IOException, ServletException {
# log.debug("HibernateSessionFilter start");
#
# try{
# //request 之前要处理的代码
# chain.doFilter(arg0, arg1);
# //response之后要要处理的代码
#
# }catch (Exception e) {
# e.printStackTrace();
# } finally{
# HibernateSessionFactory.closeSession();
# }
#
# } HibenrateSessionFacotroy是MyEclipse配置Hibernate的时候自动生成的,
大家觉得这样写处理session关闭好吗?
Session session=HibernateSessionFactory.getSession();
Transaction tx=null;
try{
tx=session.beginTransaction();
Userinfo user=new Userinfo();
user.setUserid(new Long(108));
user.setUsername("李四");
user.setUserpw("helo");
user.setUserphone("13800138000");
user.setCreatetime(new Date());
session.save(user);
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
session.close();
}
}每个方法都加fianally,然后里面写session.close()?
而非同意用filter来管理?
可以说说为什么吗?
ses.beginTransaction();
//.....(CRUD操作)...
ses.getTransaction().commit();这样就可以获得当前线程的唯一session。
这样做的优点:
1)非常适合web程序,并发管理十分容易,session由线程产生,且能够保证一个线程总是只有一个session。
2)资源回收变得轻松。session将在commit()或rollback()后自动释放,无需再写finally语句块。
3)事务管理十分直观,一般来说在业务层或service层的方法前后用上面的三个语句包住,就可以让该方法的原子性得到保证。
4)由于3)的方式应用十分普遍,用spring AOP对service层进行事务控制就更简单了,上面三行代码甚至都不必写。
5)永远不用在DAO的方法内做开启session、打开事务、提交事务、释放session这些事了,一般来说这可不是什么好习惯。
需要的额外配置:
1) 在hibernate.cfg.xml的<sessionFactory>里添加这样一行:
<property name="current_session_context_class">thread</property>
也就是说让线程来管理
2)没了。
19楼的兄弟就是我的意思,在用个不恰当的比喻: 上厕所包括 拉拉链,掏那活儿 ,吁吁 ,拉上拉链 这是一整套流程 应该放到transaction当中,否则不是一次成功的上厕所。
而放到finally里面的意思就像不管中间发生什么 最后就是拉拉链。不能保证一次有质量的排泄行为。
仁兄的意思是Struts+Hibenate3.2的session应该是像如下写法:public void testSave(){
Session session=HibernateSessionFactory.getSessionFactory().getCurrentSession();
try{
session.beginTransaction();
Userinfo user=new Userinfo();
user.setUserid(new Long(109));
user.setUsername("109");
user.setUserpw("helo");
user.setUserphone("13800138000");
user.setCreatetime(new Date());
session.save(user);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}
}
然后配置<property name="current_session_context_class">thread</property>这样session将会自动释放
public List findPage(final int currPage, final Map args,
final Class classname,final String order) {
if (args == null) {
return null;
}
final int currPate = currPage * 1;
final Map map = args;
String sql = "from " + classname.getName() + " entity where 1 = 1";
for (Iterator iter = map.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
sql = sql + " and " + key + " like '%" + map.get(key) + "%' ";
}
if(order!=null&&!"".equals(order)){
sql+= " order by "+order+" desc";
}
final String hql = sql;
List list = this.getHibernateTemplate().executeFind(
new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query query = session.createQuery(hql);
List result = query.setFirstResult(
currPage > 1 ? (currPage - 1) * 15 : 0)
.setMaxResults(15).list();
return result;
}
}); return list;
}
在这个例子中还有什么方法让他运行的快一点,因为我运行多了就变慢,我也不值到问题在哪里?
Session session=HibernateSessionFactory.getSession();
Transaction tx=null;
try{
tx=session.beginTransaction();
Userinfo user=new Userinfo();
user.setUserid(new Long(108));
user.setUsername("李四");
user.setUserpw("helo");
user.setUserphone("13800138000");
user.setCreatetime(new Date());
session.save(user);
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
session.close();
}
}
而非这样处理
Session ses = HibernateSessionFactory.getSessionFactory.getCurrentSession();
ses.beginTransaction();
//.....(CRUD操作)...
ses.getTransaction().commit(); 刚接触Hibernate,所以麻烦指教指教,呵呵
及其覆盖的Servlet和其他对象)对此Session的实例进行重用,保证了一个HttpRequest
处理过程中只占用一个Session,提高了整体性能表现
我想请教下,Filter处理Session.close()和21楼的写法比较,优缺点是什么?
也不仅仅是这样,finally也可以写,但是应该写在service层的方法两端而不是DAO里,如此以该service方法为顶端的整个调用栈里的CRUD操作都将被transaction管理,一损俱损一荣俱荣。不宜在DAO的方法里设定事务单元,颗粒度太细了。前面说过,只要设定:
<property name="current_session_context_class">thread</property>
那么事务无论提交还是回滚,session都将自动释放,所以finally不是必要的,还降低了程序的可读性。此外,当你使用Hibernate3.2或以后的版本,如无要求对事务执行中抛出的异常进行特殊处理,try catch 甚至都不需要。Hibernate的回滚原理,是必须RuntimeException以上的异常级别才会自动回滚,如果是普通的Exception则不会回滚,需要程序员手工在catch里面回滚。但Hibernate3.2以后抛出的都是RuntimeException,所以try catch也无必要了。
这个问题要寻根究底,只有看Filter的实现源码才能知道。不过就我所知,使用getCurrentSession()的方式获取的session,是在commit()、rollback()或线程生命周期结束后会自动调用session.close()的,不出意外的话,两者是一致的。此外说明一点,如果使用JPA做事务管理,那么我的方法就不能用了。当然,一般来说不会有谁吃饱了撑着非要用JPA这样重型的事务机制,只有需要处理跨数据库事务时才有用。
怪不得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;
}
}
Session session=HibernateSessionFactory.getSessionFactory().getCurrentSession();
try{
session.beginTransaction();
session.save(user);
session.getTransaction().commit();
}catch(RuntimeException e){
//session.getTransaction().rollback 自动个还是需手动
e.printStackTrace();
}
}
[/code]默认情况下Hibernate只有遇到运行时异常,数据库操作才会回滚,普通异常不会回滚
那么这个回滚是自动回滚吗?还是说需要手动回滚
RuntimeException 是自动回滚,普通Exception需要你自己在catch里面回滚。比如,有的时候异常是transaction活动期间的其它非数据库操作引起的,但由于某方面的考虑,需要回滚该transaction内的所有数据库操作,这个时候“可能”需要你手动回滚。
PS:学习框架,直接做项目才是王道。框架其实都不难的,难的话还用它做什么呢,框架的目的就是让工作变得简单。不过最难的是没有机会用在项目里,毕竟大多数时候项目要用到什么技术、框架,都是老板说了算而不是你。
catch(RuntimeException e){
session.getTransaction().rollback
e.printStackTrace();
}
也就是说在catch里面手动回滚是最保险的操作?
确实是做项目才是最好的方法
说是这么说,谁也都知道,荷包里的钞票要自己亲手数过的才放心,可是你也看到,银行柜台数大票往往还要借助于点钞机,为啥呢,因为人是动物啊,同一个机械动作做久了,你的故障率比机器可高多了。Hibernate实现自动回滚也是这个道理啊,一般情况下我们不用去管了,我们有限的精力应该放在特别不敢放心的地方,在那里手动控制回滚。
我就是往数据库里插入记录,前几条还没事,但是后来就出现了问题了
点添加等好长时间然后就出错了
我怀疑是session占用的过多没有释放,而没有可用的session资源了
不知道这个问题怎么解决 ?
从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;
}