什么是连接池,为什么要诞生这个技术??
负责的作用:管理连接,包含分配连接,新增连接,释放连接。
连接指的是:TCP连接(数据库连接,需要url,port,password,username等信息)
连接池:出现的用途,是为了防止同一个电脑(用户),每次操作完成之后,就关闭连接,然后每次操作,又要连接,浪费时间。
未使用连接池
使用连接池
常见的连接池技术有:druid,c3p0等
连接池相关的几个技术参数
- 最小连接数(池中最小的连接数量,不能设置过大,浪费资源)
- 最大连接数(如果连接超过这个数量,会加入等待队列)
- 最大空闲时间(当连接很长时间没有发送连接的时候,会断开连接)
- 获取连接超时时间
- 超时重试连接次数
连接池技术怎么保证事物问题
当2个线程共用一个连接Connection对象,而且各自都有自己的事务要处理时候,对于连接池是一个很头疼的问题,因为即使Connection类提供了相应的事务支持,可是我们仍然不能确定那个数据库操作是对应那个事务的,这是由于我们有2个线程都在进行事务操作而引起的。为此我们可以使用每一个事务独占一个连接来实现,虽然这种方法有点浪费连接池资源但是可以大大降低事务管理的复杂性
思考Mybatis的二级缓存
为什么要缓存
避免应用程序频繁的执行相同的sql,浪费服务器资源。
一级缓存,只能缓存,同一个sqlSession,创建出来的mapper,不同的mapper,一级是缓存不到的。
Mybatis执行sql的过程
- sql的提取(MappedStatement)
提取的过程中,是不能丢掉函数和sql的绑定关系。
- 函数参数和sql参数处理
- 动态sql的解析和替换
- sql的执行分类(CallableStatement,PrepareStatement)
- 函数的返回结果和sql结果集的处理
- sql的执行(SqlSession->BaseExecutor)
使用代理涉及模式,通过工厂创建的SqlSession的默认是实现DefaultSqlSession。然后执行的sql的是交给BaseExecutor子类实现。
- sqlSession的门面对象
- 真正的执行sql执行器 BaseExecutor
- 结果集处理ResultHandler
核心组件
- 用户交互对象,SqlSession
- sql的执行器,BaseExecutor
- 结果处理器,ResultHandler
- 分装sql和执行函数的对应关系,MappedStatement
缓存主键key的生成
//创建缓存Key
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
//MyBatis 对于其 Key 的生成采取规则为:[mappedStementId + offset + limit + SQL + queryParams + environment]生成一个哈希码
cacheKey.update(ms.getId());
cacheKey.update(Integer.valueOf(rowBounds.getOffset()));
cacheKey.update(Integer.valueOf(rowBounds.getLimit()));
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
//模仿DefaultParameterHandler的逻辑,不再重复,请参考DefaultParameterHandler
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
cacheKey.update(value);
}
}
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}