Session的clear方法和flush方法 .

本文详细介绍了在使用Hibernate时如何利用SessionClear()和Flush()方法来管理和更新缓存及数据库之间的数据同步。通过实例演示了这两种方法在不同场景下的具体作用,包括缓存清理和强制数据同步到数据库的操作。

Session Clear()与 Flush() 解释

 


 

 

1.Clear 方法
  无论是Load 还是 Get 都会首先查找缓存(一级缓存) 如果没有,才会去数据库查找,调用Clear() 方法,可以强制清除Session缓存。

 

例:

 
  1. public void testClear(){  
  2.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  3.         session.beginTransaction();  
  4.         Teacher t = (Teacher) session.get(Teacher.class3);  
  5.         System.out.println(t.getName());  
  6.         Teacher t2 = (Teacher) session.get(Teacher.class3);  
  7.         System.out.println(t2.getName());  
  8.         session.getTransaction().commit();  
  9.     }  
public void testClear(){
		Session session =  HibernateUitl.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Teacher t = (Teacher) session.get(Teacher.class, 3);
		System.out.println(t.getName());
		Teacher t2 = (Teacher) session.get(Teacher.class, 3);
		System.out.println(t2.getName());
		session.getTransaction().commit();
	}

 

 

这里虽然用了2个get方法(get方法会立即执行sql语句),但因为第一次执行了会缓存一个ID为3的实体,所以虽然有2个get方法只执行一次SQL语句。

 

  1. public void testClear(){  
  2.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  3.         session.beginTransaction();  
  4.         Teacher t = (Teacher) session.get(Teacher.class3);  
  5.         System.out.println(t.getName());  
  6.         session.clear();//这里不clear只会执行一次sql语句,有clear会执行2次  
  7.         Teacher t2 = (Teacher) session.get(Teacher.class3);  
  8.         System.out.println(t2.getName());  
  9.         session.getTransaction().commit();  
  10.     }  
public void testClear(){
		Session session =  HibernateUitl.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Teacher t = (Teacher) session.get(Teacher.class, 3);
		System.out.println(t.getName());
		session.clear();//这里不clear只会执行一次sql语句,有clear会执行2次
		Teacher t2 = (Teacher) session.get(Teacher.class, 3);
		System.out.println(t2.getName());
		session.getTransaction().commit();
	}

 

这里在第2次get前执行session.clear(),我们把hibernate show_sql 出来,它就会执行2次sql语句了。

 

所以session.clear()会清除缓存。

 

 

2.Flush方法
  可以强制进行从内存到数据库的同步。

 

例:

 

  1. @Test  
  2.     /** 
  3.      * flush 强制与数据库同步 
  4.      */  
  5.     public void testFlush(){  
  6.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  7.         session.beginTransaction();  
  8.         Teacher t = (Teacher) session.get(Teacher.class3);  
  9.         t.setName("yyy");  
  10.    
  11.         t.setName("yyyyy");  
  12.         session.getTransaction().commit();  
  13.     }  
@Test
	/**
	 * flush 强制与数据库同步
	 */
	public void testFlush(){
		Session session =  HibernateUitl.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Teacher t = (Teacher) session.get(Teacher.class, 3);
		t.setName("yyy");
 
		t.setName("yyyyy");
		session.getTransaction().commit();
	}




 

 

看这段代码,我们setName() 2次, 但程序只会更改数据库一次,在commit时。

 

  1. @Test  
  2.     /** 
  3.      * flush 强制与数据库同步 
  4.      */  
  5.     public void testFlush(){  
  6.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  7.         session.beginTransaction();  
  8.         Teacher t = (Teacher) session.get(Teacher.class3);  
  9.         t.setName("yyy");  
  10.         session.flush();//有flush会执行2次UPDAE,没有会只执行一次  
  11.         t.setName("yyyyy");  
  12.         session.getTransaction().commit();  
  13.     }  
@Test
	/**
	 * flush 强制与数据库同步
	 */
	public void testFlush(){
		Session session =  HibernateUitl.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Teacher t = (Teacher) session.get(Teacher.class, 3);
		t.setName("yyy");
		session.flush();//有flush会执行2次UPDAE,没有会只执行一次
		t.setName("yyyyy");
		session.getTransaction().commit();
	}




 

 

 

我们在第2次setName()时 执行session.flush().

 

再看hibernate 执行的sql 语句

 

  1. Hibernate:   
  2.     update  
  3.         Teacher   
  4.     set  
  5.         birthday=?,  
  6.         name=?,  
  7.         title=?   
  8.     where  
  9.         id=?  
  10. Hibernate:   
  11.     update  
  12.         Teacher   
  13.     set  
  14.         birthday=?,  
  15.         name=?,  
  16.         title=?   
  17.     where  
  18.         id=?  
Hibernate: 
    update
        Teacher 
    set
        birthday=?,
        name=?,
        title=? 
    where
        id=?
Hibernate: 
    update
        Teacher 
    set
        birthday=?,
        name=?,
        title=? 
    where
        id=?




 

执行了2次Update

 

所以看出来flush方法会强制与数据库同步。

 

 


 

Flush方法是可以设置的,也就是fulsh什么时候执行是可以设置的

 

 在session.beginTransaction前设置FlushMode

 

session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL)

 

FlushMode有5个值可选

Always:任何代码都会Flush
AUTO:默认方式–自动
Commit:COMMIT时
Never:始终不
MANUAL:手动方式

<think>嗯,用户现在想了解Django中的request.session.set_expiry方法的使用方法参数说明。我需要先回忆一下Django的session机制,然后结合用户提供的引用内容来组织答案。 首先,根据引用[2][4],用户提到了request.session属性的使用,包括设置过期时间flushclear方法。用户特别提到了set_expiry,所以需要详细解释这个方法。 我记得Django的session框架允许设置会话的过期时间。set_expiry方法用于设置会话的过期时间,参数可以是整数、datetime对象或者特定值如0或None。需要明确说明不同参数的作用。 然后,用户可能想知道如何实际应用这个方法,比如在视图中设置,或者处理浏览器关闭后的情况。需要举几个例子,比如设置30分钟后过期,或者使用浏览器会话期。 还要注意错误处理,比如参数类型的错误,或者使用datetime对象时的时区问题。Django默认使用时区,所以需要提醒用户注意。 另外,用户提供的引用中有提到使用login_required装饰器,可能涉及到会话管理,但用户的问题主要集中在set_expiry上,所以重点放在这个方法上。 可能需要分点说明参数类型、示例代码、注意事项,以及常见问题。比如,0表示浏览器关闭后过期,None表示使用全局设置等。同时,结合用户的引用,可以引用相关的文档部分,比如Django的官方文档说明。 还要考虑用户可能遇到的常见问题,比如设置后没有生效,可能因为中间件配置问题,或者浏览器不支持cookie等。需要提醒用户检查这些方面。 最后,确保回答结构清晰,步骤明确,代码示例正确,并且覆盖用户可能需要的各种使用场景。可能还需要对比其他方法,比如全局设置SESSION_COOKIE_AGE,set_expiry的区别,让用户了解何时使用哪种方法。</think>### Django中`request.session.set_expiry()`方法详解 #### 一、核心功能 `request.session.set_expiry(value)`用于**精准控制会话(Session)的过期时间**,支持多种参数类型[^2][^4]。该方法直接影响当前请求关联的会话生命周期。 #### 二、参数类型与行为 | 参数类型 | 行为描述 | |--------------------|------------------------------------------------------------------------| | **整数** | 以秒为单位的绝对过期时间(从当前时间计算) | | **datetime对象** | 指定精确的到期时间点(需使用时区aware对象) | | **0** | 会话在浏览器关闭时失效(依赖浏览器Cookie机制) | | **None** | 使用全局默认设置`SESSION_COOKIE_AGE`(默认两周=1209600秒) | #### 三、基础用法示例 1. **设置30分钟后过期** ```python def my_view(request): request.session['user_data'] = {'id': 123} request.session.set_expiry(1800) # 30*60秒 return HttpResponse("会话将在30分钟后过期") ``` 2. **使用浏览器会话期** ```python def login(request): if auth_success: request.session.set_expiry(0) # 关闭浏览器即失效 return redirect('/dashboard') ``` 3. **指定具体到期时间点** ```python from django.utils import timezone expiry_time = timezone.now() + timezone.timedelta(hours=2) request.session.set_expiry(expiry_time) ``` #### 四、关键注意事项 1. **时区敏感** 使用`datetime`对象时必须确保为时区aware对象(通过`timezone`模块创建),否则会触发`ValueError`[^4] 2. **持久化触发时机** 修改会话数据后必须显式调用`request.session.modified = True`才会保存过期时间设置(Django 1.8+默认自动检测数据变更) 3. **全局配置覆盖** 若同时存在全局配置`SESSION_COOKIE_AGE``set_expiry()`调用,以最后一次设置的值为准 #### 五、调试技巧 1. **查看当前会话过期时间** ```python print(request.session.get_expiry_date()) # 返回datetime对象 print(request.session.get_expiry_age()) # 返回剩余秒数 ``` 2. **强制清理过期会话** 定期运行Django管理命令清理数据库: ```bash python manage.py clearsessions ``` #### 六、常见问题解决方案 **问题:设置后未生效** - 检查中间件配置是否包含`django.contrib.sessions.middleware.SessionMiddleware` - 验证浏览器是否禁用Cookie - 使用Chrome开发者工具检查响应头`Set-Cookie`中的`Expires/Max-Age`值 **问题:时区报错** ```python # 错误写法(naive时间) request.session.set_expiry(datetime.datetime.now() + datetime.timedelta(days=1)) # 正确写法(aware时间) from django.utils import timezone request.session.set_expiry(timezone.now() + timezone.timedelta(days=1)) ``` #### 七、高级用法 **结合用户登录状态** ```python from django.contrib.auth.decorators import login_required @login_required def sensitive_operation(request): # 高安全操作使用短会话 request.session.set_expiry(300) # 5分钟 return render(request, 'vip_page.html') ``` --- ### 相关问题 1. 如何实现Django会话的分布式存储(如Redis)? 2. 浏览器关闭后Session数据何时被清除? 3. 如何强制用户重新登录(立即终止会话)? 4. SessionCookie的安全防护措施有哪些? [^1]: Django官方认证系统文档 : Django Session处理机制 [^4]: Django会话过期控制实践
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值