- 浏览: 99362 次
- 性别:
- 来自: 北京
博客专栏
-
自己动手写java 框架
浏览量:27201
最新评论
-
zh_harry:
线上demo已经上线http://www.sparrowzoo ...
高性能轻量级markdown 解析器java 版sparrow-markdown -
zh_harry:
sp42 写道演示地址 本地的? 代码 git clone 下 ...
自己动手写mvc框架SPARROW MVC -
sp42:
非常不错 赞一个
高性能轻量级markdown 解析器java 版sparrow-markdown -
sp42:
演示地址 本地的?
自己动手写mvc框架SPARROW MVC -
sp42:
我的框架也是用原生写,已弃坑。还是 MVVM 的爽,推荐 vu ...
SPARROW-JS 从0开始写 0依赖,原生JS框架
关于sqlsession我们先看这些问题:
我们做web开发,很容易联系到http的session,那么它跟进http的session有关系吗?
如果非要映射到web开发中的某个对象他到底跟哪个对象很象呢?
sqlssion是用来做什么的?
如果只是数据库连接为什么不直接用sqlconnection呢?
我们从配置文件可以看出他由sqlsessionfactory产生,sqlsessionfactory需要datasource.那么datasouce是什么呢?
它跟数据库连接池有什么关系呢?
sqlsession是线程安全的吗?
最后一个问题很有代表性,关于线程安全问题接下来会专门写一篇文章跟大家分享。
2.1.5.3 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 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:
这是mybatis 官方文档的解释
这里说sqlssion是线程不安全的,它不应该被定成static变量或者类的成员变量,因此最好定义成request域或方法变量(局部变量)
Never keep references
to a SqlSession instance in a static field or even an instance field of a class
不要象servlet框架的httpsession那样 保持对象引用。
Never keep references
to a SqlSession in any sort of managed scope, such as HttpSession of of the Servlet framework
如果我们用象servlet这样的web框架,那么它象httprequest.(这里明确说明了,sqlsession跟request对象很象),后边又强调,即在接收到request请求时打sqlsession.在用response返回时一定要关闭sqlssion
这里明确说明关闭很重要,而且用finally{}块(finally一般用于资源释放)
这里已经回答了sqlssion是什么?
sqlsession是用来做什么的?
其实我认为他是用来管理事务的,(实际上也应该是这样)
因为每次请求相当启动一个数据库事务,本次请求可能连接N(N>=0)次数据库,如果我们每次数据库连接都要从重新获取(或者都要从池中获取)这是一种资源浪费,而且从事务角度来考虑也是不对的,这里是threadlocal典型的应用场景。
这里还有一个问题datasource和数据库连接池有什么区别和联系?
数据库连接池是datasource的一种实现
这是jdk package javax.sql.dataSource的注释
说得很明白,其实数据库连接池就是datasource的一种实现,这个接口只提供了getconnection方法?那么我们怎么关闭呢?
这篇文章有介绍
http://lizhizhang.iteye.com/blog/1904058
最后一个问题它是线程安全的吗?
sqlsession本身只是一个接口,所以是否线程安全不能从接口上下定论,因为mybatis对sqlsession的实现
前两个是mybatis的实现都是线程不安全的
最后一个是mybatis-spring中间件的线程安全实现
这是sqlsessiontemplate的源码及注释
因为每次请求相当启动一个数据库事务,本次请求可能连接N(N>=0)次数据库,如果我们每次数据库连接都要从重新获取(或者都要从池中获取)这是一种资源浪费,而且从事务角度来考虑也是不对的,这里是threadlocal典型的应用场景。
这种说法是不对的,事务是数据存取层的概念,而请求/响应是web交互层上的概念,分离开来很好,掺和在一起太乱了。
效率当然是考虑问题的一个重要方面,但是清晰是对架构的本质性要求。
我们做web开发,很容易联系到http的session,那么它跟进http的session有关系吗?
如果非要映射到web开发中的某个对象他到底跟哪个对象很象呢?
sqlssion是用来做什么的?
如果只是数据库连接为什么不直接用sqlconnection呢?
我们从配置文件可以看出他由sqlsessionfactory产生,sqlsessionfactory需要datasource.那么datasouce是什么呢?
它跟数据库连接池有什么关系呢?
sqlsession是线程安全的吗?
最后一个问题很有代表性,关于线程安全问题接下来会专门写一篇文章跟大家分享。
2.1.5.3 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 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:
这是mybatis 官方文档的解释
这里说sqlssion是线程不安全的,它不应该被定成static变量或者类的成员变量,因此最好定义成request域或方法变量(局部变量)
Never keep references
to a SqlSession instance in a static field or even an instance field of a class
不要象servlet框架的httpsession那样 保持对象引用。
Never keep references
to a SqlSession in any sort of managed scope, such as HttpSession of of the Servlet framework
如果我们用象servlet这样的web框架,那么它象httprequest.(这里明确说明了,sqlsession跟request对象很象),后边又强调,即在接收到request请求时打sqlsession.在用response返回时一定要关闭sqlssion
这里明确说明关闭很重要,而且用finally{}块(finally一般用于资源释放)
这里已经回答了sqlssion是什么?
sqlsession是用来做什么的?
其实我认为他是用来管理事务的,(实际上也应该是这样)
因为每次请求相当启动一个数据库事务,本次请求可能连接N(N>=0)次数据库,如果我们每次数据库连接都要从重新获取(或者都要从池中获取)这是一种资源浪费,而且从事务角度来考虑也是不对的,这里是threadlocal典型的应用场景。
这里还有一个问题datasource和数据库连接池有什么区别和联系?
数据库连接池是datasource的一种实现
这是jdk package javax.sql.dataSource的注释
/* * %W% %E% * * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package javax.sql; import java.sql.Connection; import java.sql.SQLException; import java.sql.Wrapper; /** * <p>A factory for connections to the physical data source that this * <code>DataSource</code> object represents. An alternative to the * <code>DriverManager</code> facility, a <code>DataSource</code> object * is the preferred means of getting a connection. An object that implements * the <code>DataSource</code> interface will typically be * registered with a naming service based on the * Java<sup><font size=-2>TM</font></sup> Naming and Directory (JNDI) API. * <P> * The <code>DataSource</code> interface is implemented by a driver vendor. * There are three types of implementations: * [list=1] * <LI>Basic implementation -- produces a standard <code>Connection</code> * object * <LI>Connection pooling implementation -- produces a <code>Connection</code> * object that will automatically participate in connection pooling. This * implementation works with a middle-tier connection pooling manager. * <LI>Distributed transaction implementation -- produces a * <code>Connection</code> object that may be used for distributed * transactions and almost always participates in connection pooling. * This implementation works with a middle-tier * transaction manager and almost always with a connection * pooling manager. * [/list] * <P> * A <code>DataSource</code> object has properties that can be modified * when necessary. For example, if the data source is moved to a different * server, the property for the server can be changed. The benefit is that * because the data source's properties can be changed, any code accessing * that data source does not need to be changed. * <P> * A driver that is accessed via a <code>DataSource</code> object does not * register itself with the <code>DriverManager</code>. Rather, a * <code>DataSource</code> object is retrieved though a lookup operation * and then used to create a <code>Connection</code> object. With a basic * implementation, the connection obtained through a <code>DataSource</code> * object is identical to a connection obtained through the * <code>DriverManager</code> facility. * * @since 1.4 */ public interface DataSource extends CommonDataSource,Wrapper { /** * <p>Attempts to establish a connection with the data source that * this <code>DataSource</code> object represents. * * @return a connection to the data source * @exception SQLException if a database access error occurs */ Connection getConnection() throws SQLException; /** * <p>Attempts to establish a connection with the data source that * this <code>DataSource</code> object represents. * * @param username the database user on whose behalf the connection is * being made * @param password the user's password * @return a connection to the data source * @exception SQLException if a database access error occurs * @since 1.4 */ Connection getConnection(String username, String password) throws SQLException; }
说得很明白,其实数据库连接池就是datasource的一种实现,这个接口只提供了getconnection方法?那么我们怎么关闭呢?
这篇文章有介绍
http://lizhizhang.iteye.com/blog/1904058
最后一个问题它是线程安全的吗?
sqlsession本身只是一个接口,所以是否线程安全不能从接口上下定论,因为mybatis对sqlsession的实现
前两个是mybatis的实现都是线程不安全的
最后一个是mybatis-spring中间件的线程安全实现
/* * Copyright 2010-2013 The MyBatis Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mybatis.spring; import static java.lang.reflect.Proxy.newProxyInstance; import static org.apache.ibatis.reflection.ExceptionUtil.unwrapThrowable; import static org.mybatis.spring.SqlSessionUtils.closeSqlSession; import static org.mybatis.spring.SqlSessionUtils.getSqlSession; import static org.mybatis.spring.SqlSessionUtils.isSqlSessionTransactional; import static org.springframework.util.Assert.notNull; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.sql.Connection; import java.util.List; import java.util.Map; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.executor.BatchResult; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.dao.support.PersistenceExceptionTranslator; /** * Thread safe, Spring managed, {@code SqlSession} that works with Spring * transaction management to ensure that that the actual SqlSession used is the * one associated with the current Spring transaction. In addition, it manages * the session life-cycle, including closing, committing or rolling back the * session as necessary based on the Spring transaction configuration. * <p> * The template needs a SqlSessionFactory to create SqlSessions, passed as a * constructor argument. It also can be constructed indicating the executor type * to be used, if not, the default executor type, defined in the session factory * will be used. * <p> * This template converts MyBatis PersistenceExceptions into unchecked * DataAccessExceptions, using, by default, a {@code MyBatisExceptionTranslator}. * <p> * Because SqlSessionTemplate is thread safe, a single instance can be shared * by all DAOs; there should also be a small memory savings by doing this. This * pattern can be used in Spring configuration files as follows: * ** {@code * <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> * <constructor-arg ref="sqlSessionFactory" /> * </bean> * } *
*
* @see SqlSessionFactory
* @see MyBatisExceptionTranslator
* @version $Id$
*/
public class SqlSessionTemplate implements SqlSession {
private final SqlSessionFactory sqlSessionFactory;
private final ExecutorType executorType;
private final SqlSession sqlSessionProxy;
private final PersistenceExceptionTranslator exceptionTranslator;
/**
* Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
* provided as an argument.
*
* @param sqlSessionFactory
*/
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
}
/**
* Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
* provided as an argument and the given {@code ExecutorType}
* {@code ExecutorType} cannot be changed once the {@code SqlSessionTemplate}
* is constructed.
*
* @param sqlSessionFactory
* @param executorType
*/
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
this(sqlSessionFactory, executorType,
new MyBatisExceptionTranslator(
sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
}
/**
* Constructs a Spring managed {@code SqlSession} with the given
* {@code SqlSessionFactory} and {@code ExecutorType}.
* A custom {@code SQLExceptionTranslator} can be provided as an
* argument so any {@code PersistenceException} thrown by MyBatis
* can be custom translated to a {@code RuntimeException}
* The {@code SQLExceptionTranslator} can also be null and thus no
* exception translation will be done and MyBatis exceptions will be
* thrown
*
* @param sqlSessionFactory
* @param executorType
* @param exceptionTranslator
*/
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) {
notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
notNull(executorType, "Property 'executorType' is required");
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
}
public SqlSessionFactory getSqlSessionFactory() {
return this.sqlSessionFactory;
}
public ExecutorType getExecutorType() {
return this.executorType;
}
public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
return this.exceptionTranslator;
}
/**
* {@inheritDoc}
*/
public <T> T selectOne(String statement) {
return this.sqlSessionProxy.<T> selectOne(statement);
}
/**
* {@inheritDoc}
*/
public <T> T selectOne(String statement, Object parameter) {
return this.sqlSessionProxy.<T> selectOne(statement, parameter);
}
/**
* {@inheritDoc}
*/
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
return this.sqlSessionProxy.<K, V> selectMap(statement, mapKey);
}
/**
* {@inheritDoc}
*/
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey);
}
/**
* {@inheritDoc}
*/
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey, rowBounds);
}
/**
* {@inheritDoc}
*/
public <E> List<E> selectList(String statement) {
return this.sqlSessionProxy.<E> selectList(statement);
}
/**
* {@inheritDoc}
*/
public <E> List<E> selectList(String statement, Object parameter) {
return this.sqlSessionProxy.<E> selectList(statement, parameter);
}
/**
* {@inheritDoc}
*/
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return this.sqlSessionProxy.<E> selectList(statement, parameter, rowBounds);
}
/**
* {@inheritDoc}
*/
public void select(String statement, ResultHandler handler) {
this.sqlSessionProxy.select(statement, handler);
}
/**
* {@inheritDoc}
*/
public void select(String statement, Object parameter, ResultHandler handler) {
this.sqlSessionProxy.select(statement, parameter, handler);
}
/**
* {@inheritDoc}
*/
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
}
/**
* {@inheritDoc}
*/
public int insert(String statement) {
return this.sqlSessionProxy.insert(statement);
}
/**
* {@inheritDoc}
*/
public int insert(String statement, Object parameter) {
return this.sqlSessionProxy.insert(statement, parameter);
}
/**
* {@inheritDoc}
*/
public int update(String statement) {
return this.sqlSessionProxy.update(statement);
}
/**
* {@inheritDoc}
*/
public int update(String statement, Object parameter) {
return this.sqlSessionProxy.update(statement, parameter);
}
/**
* {@inheritDoc}
*/
public int delete(String statement) {
return this.sqlSessionProxy.delete(statement);
}
/**
* {@inheritDoc}
*/
public int delete(String statement, Object parameter) {
return this.sqlSessionProxy.delete(statement, parameter);
}
/**
* {@inheritDoc}
*/
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
/**
* {@inheritDoc}
*/
public void commit() {
throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
public void commit(boolean force) {
throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
public void rollback() {
throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
public void rollback(boolean force) {
throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
public void close() {
throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
}
/**
* {@inheritDoc}
*/
public void clearCache() {
this.sqlSessionProxy.clearCache();
}
/**
* {@inheritDoc}
*
*/
public Configuration getConfiguration() {
return this.sqlSessionFactory.getConfiguration();
}
/**
* {@inheritDoc}
*/
public Connection getConnection() {
return this.sqlSessionProxy.getConnection();
}
/**
* {@inheritDoc}
*
* @since 1.0.2
*
*/
public List<BatchResult> flushStatements() {
return this.sqlSessionProxy.flushStatements();
}
/**
* Proxy needed to route MyBatis method calls to the proper SqlSession got
* from Spring's Transaction Manager
* It also unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to
* pass a {@code PersistenceException} to the {@code PersistenceExceptionTranslator}.
*/
private class SqlSessionInterceptor implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
这是sqlsessiontemplate的源码及注释
评论
2 楼
windshome
2013-08-06
因为每次请求相当启动一个数据库事务,本次请求可能连接N(N>=0)次数据库,如果我们每次数据库连接都要从重新获取(或者都要从池中获取)这是一种资源浪费,而且从事务角度来考虑也是不对的,这里是threadlocal典型的应用场景。
这种说法是不对的,事务是数据存取层的概念,而请求/响应是web交互层上的概念,分离开来很好,掺和在一起太乱了。
效率当然是考虑问题的一个重要方面,但是清晰是对架构的本质性要求。
1 楼
zh_harry
2013-08-02
发帖之前去吃饭了,补充一句,因为sessiontemplate是线程安全的,而mybatis官方文档的说明讲的都是mybatis自己的实现,不要被官方说明所误导,我们用mybatis-spring的SqlSessionDaoSupport不会有线程问题。
发表评论
-
零基础小白从0到1的spring cloud alibaba 全家桶项目
2022-10-18 02:15 2437零基础暖心计划课程内容 https://spar ... -
sparrow 支持JDK依赖注入功能
2022-08-02 15:28 1903麻雀虽小,但五脏俱全 sparrow 源自中国俗语 ... -
Sparrow js 框架开源上线
2019-06-29 21:28 941sparraw 框架js 版开源上线 www.sparr ... -
SPARROW-JS 从0开始写 0依赖,原生JS框架
2018-03-15 19:52 1564SPARROW-JS 前端JS框架变幻莫测,但原生js 接口 ... -
Sparrow算法篇 从日期取交集到思维模式-2
2018-03-09 18:04 1438接上一篇 Sparrow算法篇 从日期取交集到思维模式 ... -
高性能轻量级markdown 解析器java 版sparrow-markdown
2018-02-24 17:17 4056动机 markdown 已成为网络博客最主要的排版格式。 ... -
Sparrow 算法篇 由日期取交集到思维模式
2018-02-06 23:46 1661日期交集 早在13年左右的时侯,做过一个系统,功能很简单 ... -
自己动手写mvc框架SPARROW MVC
2018-02-01 22:31 1487SPARROW-MVC SPARROW-MVC 是SPA ... -
REDIS客户端封装实践2
2018-01-30 13:32 1050接上一篇 [REDIS客户端封装意淫](https:// ... -
SPARROW 框架redis客户端封装实践
2018-01-25 21:41 1083redis 本身有客户端,先抛出来一个问题?为什么要对red ... -
SPARROW架构介绍
2018-01-24 22:02 1233sparrow 框架设计最大化解耦,理论上业务层只依赖SPA ... -
Sparrow 框架设计哲学
2018-01-24 13:21 1199sparrow 框架 麻雀虽小,但五脏俱全 为什么要写这 ... -
tomcat 日志那点事
2017-07-15 14:06 739tomcat 启动时使用的是java.util.logger ... -
疯子在思考之-异常与return 的差别
2013-10-14 14:46 1369程序异常会中断程序执行,所有所有的异常都需要捕获,否则会 ... -
MANIFEST.MF 文件内容完全详解
2013-09-02 14:49 1252打开Java的JAR文件我们经常可以看到文件中包含着一个ME ... -
疯子奉献-一个符号惹的祸
2013-08-30 14:14 1710程序员是严谨的,但是再严谨也容易出问题,这就叫做bug。 我 ... -
疯子在思考之-从日志想到的软件架构
2013-08-28 18:57 1871谈到架构是一个很泛的话题 这里我们讨论一下兼容性与扩展性 ... -
疯子在思考之java 线程的那点事儿
2013-08-14 15:13 3217很长时间没写博客了,最近事情比较多 之前在文章中提到过tomc ... -
linux 自动重启tomcat 脚本
2013-08-12 17:59 2935Tomcat作为开源的服务器 ... -
tomcat 优化及错误All threads (10) are currently busy, waiting. Increase maxThreads错误
2013-08-12 17:42 15251. 如何加大tomcat连接数 在tomcat配置文件se ...
相关推荐
free-idea-mybatis is an enchange plugin for idea to supoort mybatis,here is the main functions: generate mapper xml files navigate from the code to mapper and from the mapper back to code auto code...
free-idea-mybatis是一个提高mybatis编码的插件。实现了dao代码跳转到mapper,mapper跳转回dao,mapper文件、statement查询自动生成...这里提供两个版本free-idea-mybatis-2019.12.18 和free-idea-mybatis-2018.05.17
该项目应用Springboot框架,MyBatis持久层与Sqlsession映射进行数据查询
mybatis源码是mybatis-3.2.6的源码,用户使用mybatis时可以进行参考
idea free-idea-mybatis-2019.12.18插件(原文件名已存在,则换了个资源名),直接下载解压即可
jeecg-mybatis-framework20131220.zipjeecg-mybatis-framework20131220.zipjeecg-mybatis-framework20131220.zipjeecg-mybatis-framework20131220.zipjeecg-mybatis-framework20131220.zipjeecg-mybatis-framework...
free-idea-mybatis2020.9.15
mybatis-3-mybatis-3.3.0.zip
mybatis获取SqlSession源代码流程
java操作数据库的mybatis框架所需要的源码包以及mybatis-3-mybatis-3.3.0.rar包
基于SpringMVC Mybatis Shiro Redis 的权限管理系统,该系统已经部署到线上,线上访问地址:http://shiro.itboy.net,登录账号:admin 密码:sojson,,详细教程参考sojson.com/shiro
SpringMVC-Mybatis-Shiro-redis-master..............
spring-mybatis整合jar包spring-mybatis整合jar包spring-mybatis整合jar包
springboot-mybatis-demo
基于SpringMVC、Mybatis、Redis、Freemarker的Shiro管理Demo源码的升级版 相关详细配置说明请参看 --> http://www.sojson.com/shiro
Idea mybatis 插件 ,xml 各种提示 ,dao 层可以直接在 xml 文件生成方法,也可直接跳转到 xml
mybatis-3-mybatis-3.4.6框架包 mybatis-3-mybatis-3.4.6.tar
reactive-mybatis-support-examples-master.zip
ideamybatis插件-能直接跳转到看sql
echarts-spring-mybatis-masterecharts-spring-mybatis-masterecharts-spring-mybatis-masterecharts-spring-mybatis-masterecharts-spring-mybatis-masterecharts-spring-mybatis-masterecharts-spring-mybatis-...