每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它
mybatis – MyBatis 3 | 入门 http://www.mybatis.org/mybatis-3/zh/getting-started.html
作用域(Scope)和生命周期
理解我们目前已经讨论过的不同作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。
提示 对象生命周期和依赖注入框架
依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器(mapper)并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。如果对如何通过依赖注入框架来使用 MyBatis 感兴趣可以研究一下 MyBatis-Spring 或 MyBatis-Guice 两个子项目。
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但是最好还是不要让其一直存在以保证所有的 XML 解析资源开放给更重要的事情。
SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。因此 SqlSessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的管理作用域中,比如 Servlet 架构中的 HttpSession。如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的作用域中。换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。下面的示例就是一个确保 SqlSession 关闭的标准模式:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
在你的所有的代码中一致性地使用这种模式来保证所有数据库资源都能被正确地关闭。
映射器实例(Mapper Instances)
映射器是一个你创建来绑定你映射的语句的接口。映射器接口的实例是从 SqlSession 中获得的。因此从技术层面讲,任何映射器实例的最大作用域是和请求它们的 SqlSession 相同的。尽管如此,映射器实例的最佳作用域是方法作用域。也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可废弃。并不需要显式地关闭映射器实例,尽管在整个请求作用域(request scope)保持映射器实例也不会有什么问题,但是很快你会发现,像 SqlSession 一样,在这个作用域上管理太多的资源的话会难于控制。所以要保持简单,最好把映射器放在方法作用域(method scope)内。下面的示例就展示了这个实践:
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
} mybatis – MyBatis 3 | Getting started http://www.mybatis.org/mybatis-3/getting-started.html
Scope and Lifecycle
It's very important to understand the various scopes and lifecycles classes we've discussed so far. Using them incorrectly can cause severe concurrency problems.
NOTE Object lifecycle and Dependency Injection Frameworks
Dependency Injection frameworks can create thread safe, transactional SqlSessions and mappers and inject them directly into your beans so you can just forget about their lifecycle. You may want to have a look at MyBatis-Spring or MyBatis-Guice sub-projects to know more about using MyBatis with DI frameworks.
SqlSessionFactoryBuilder
This class can be instantiated, used and thrown away. There is no need to keep it around once you've created your SqlSessionFactory. Therefore the best scope for instances of SqlSessionFactoryBuilder is method scope (i.e. a local method variable). You can reuse the SqlSessionFactoryBuilder to build multiple SqlSessionFactory instances, but it's still best not to keep it around to ensure that all of the XML parsing resources are freed up for more important things.
SqlSessionFactory
Once created, the SqlSessionFactory should exist for the duration of your application execution. There should be little or no reason to ever dispose of it or recreate it. It's a best practice to not rebuild the SqlSessionFactory multiple times in an application run. Doing so should be considered a “bad smell”. Therefore the best scope of SqlSessionFactory is application scope. This can be achieved a number of ways. The simplest is to use a Singleton pattern or Static Singleton pattern.
SqlSession
Each thread should have its own instance of SqlSession. Instances of SqlSession are not to be shared and are not thread safe. Therefore the best scope is request or method scope. Never keep references to a SqlSession instance in a static field or even an instance field of a class. Never keep references to a SqlSession in any sort of managed scope, such as HttpSession of the Servlet framework. If you're using a web framework of any sort, consider the SqlSession to follow a similar scope to that of an HTTP request. In other words, upon receiving an HTTP request, you can open a SqlSession, then upon returning the response, you can close it. Closing the session is very important. You should always ensure that it's closed within a finally block. The following is the standard pattern for ensuring that SqlSessions are closed:
SqlSession session = sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
Using this pattern consistently throughout your code will ensure that all database resources are properly closed.
Mapper Instances
Mappers are interfaces that you create to bind to your mapped statements. Instances of the mapper interfaces are acquired from the SqlSession. As such, technically the broadest scope of any mapper instance is the same as the SqlSession from which they were requested. However, the best scope for mapper instances is method scope. That is, they should be requested within the method that they are used, and then be discarded. They do not need to be closed explicitly. While it's not a problem to keep them around throughout a request, similar to the SqlSession, you might find that managing too many resources at this level will quickly get out of hand. Keep it simple, keep Mappers in the method scope. The following example demonstrates this practice.
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
}
每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它的更多相关文章
- [Java] 两种发起POST请求方法,并接收返回的响应内容的处理方式
1.利用apache提供的commons-httpclient-3.0.jar包 代码如下: /** * 利用HttpClient发起POST请求,并接收返回的响应内容 * * @param url ...
- JAVA传入一个字符串,返回一个字符串中的大写字母
/** * * @param 传入一个字符串 * @return 返回一个字符串中的大写字母 */ private static String str ...
- 编写函数,接受一个string,返回一个bool值,指出string是否有5个或者更多字符,使用此函数打印出长度大于等于5的元素
#include <algorithm> using namespace std; bool isFive(const string& s1) { return s1.size() ...
- 如何实现 Https拦截进行 非常规“抓包” 珍惜Any 看雪学院 今天 前段时间在自己做开发的时候发现一个很好用的工具,OKHttp的拦截器(何为拦截器?就是在每次发送网络请求的时候都会走的一个回调)大概效果如下:
如何实现 Https拦截进行 非常规“抓包” 珍惜Any 看雪学院 今天 前段时间在自己做开发的时候发现一个很好用的工具,OKHttp的拦截器(何为拦截器?就是在每次发送网络请求的时候都会走的一个回调 ...
- 打开tcp_tw_recycle引起的一个问题
今天普空说了一个问题就是如果设置了tcp_tw_recycle ,那么如果客户端是NAT出来的,那么就可能会出现连接被直接rst的情况.然后我google了下,在内核列表也有人说了这个问题 https ...
- Window.open 实现导航与打开窗口,导航到一个特定链接地址,也可以打开一个新的浏览器窗体
语法 window.open(strUrl,strWindowName,strWindowFeatures ,replace) strUrl: 打开资源的地址 strWindowName: 表示窗体名 ...
- 防抖与节流 & 若每个请求必须发送,如何平滑地获取最后一个接口返回的数据
博客地址:https://ainyi.com/79 日常浏览网页中,在进行窗口的 resize.scroll 或者重复点击某按钮发送请求,此时事件处理函数或者接口调用的频率若无限制,则会加重浏览器的负 ...
- 08配置基础路径 同时导出一个函数和一个变量 封装微信请求Api
地址===>https://www.bilibili.com/video/av58993009/?p=46 1==>配置基础路径同时导出一个函数和一个变量 var mynetwork= f ...
- VMware 打开虚拟机出现另一个程序已锁定文件的一部分,进程无法访问
打开虚拟机出现 另一个程序已锁定文件的一部分,进程无法访问 打不开磁盘"D:\Virtual Machines\CentOS 7 64 位\CentOS 7 64 位.vmdk"或 ...
随机推荐
- Unity3D深入浅出 -组件与节点之间的调用关系
一.transform组件用途 1.维护场景树 2.对3D物体的平移,缩放,旋转 二.场景树定义 在Hierarchy视图中显示的: 一个game_scene场景,下面有Main Camera节点,D ...
- CentOS系统中last命令的作用
CentOS系统中last命令的作用是显示近期用户或终端的登录情况,它的使用权限是所有用户.通过last命令查看该程序的log,管理员可以获知谁曾经或企图连接系统. 格式 last [—R] [—n] ...
- Json.net 时间格式处理
json.net转json时生成的时间格式是这种 2015-11-14T06:59:59+08:00 格式化为这种2015-11-14 后台代码: IsoDateTimeConverter timeF ...
- c++ 在线编译
#include <algorithm> #include <cstdlib> #include <fstream> #include <iostream&g ...
- oracle中LAG()和LEAD()以及over (PARTITION BY)
LAG()和LEAD()统计函数可以在一次查询中取出同一字段的前N行的数据和后N行的值.这种操作可以使用对相同表的表连接来实现,不过使用LAG和 LEAD有更高的效率.以下整理的LAG()和LEAD( ...
- centos7 安装zookeeper 集群
data 创建myid 设置1 zookeeper默认端口2181 同步端口 20881 和 30881 设置zoo.cfg文件
- Java精选笔记_Servlet事件监听器
Servlet事件监听器 概述 在程序开发中,经常需要对某些事件进行监听,如监听鼠标点击事件.监听键盘按下事件等,此时就需要使用事件监听器. 事件监听器用于对程序中发生的事件进行监听,在监听的过程中会 ...
- js实现卡号每四位空格分隔
window.onload =function() { document.getElementById("input_num").oninput =function() { })( ...
- GIS-013-Cesium Terrain 数据生成
一.Python 1.修改Python脚本文件 if __name__=='__main__': #sys.argv = ['F:\\000_Terrain\\T7-gdal2srtmtiles-de ...
- 【RF库Collections测试】Insert Into List
Name:Insert Into ListSource:Collections <test library>Arguments:[ list_ | index | value ]Inser ...