spring-mybatis与原生mybatis使用对比分析
原生mybatis使用方法:
string resource = "mybatis-config.xml"; inputstream inputstream = resources.getresourceasstream(resource); sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream); sqlsession session = sqlsessionfactory.opensession(); try { employee employee = new employee(null, "doubi", "1", "ddd@sys.com"); employeemapper mapper = session.getmapper(employeemapper.class); mapper.addemp(employee); session.commit(); } finally { session.close(); }
spring使用方法,直接注入即可
@autowired employeemapper employeemapper
那么spring为我们做了什么?下面研究一下mybatis-spring.jar这个jar包
首先来看一下如何使用spring整合mybatis,下面是使用spring-mybatis的四种方法:
方法一:(使用mapperfactorybean)
<bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource"/> <property name="configlocation" value="classpath:mybatis-config.xml"></property> <!-- 自动扫描mapping.xml文件 --> <property name="mapperlocations" value="classpath:mapper/*.xml"></property> </bean> <!--上面生成sqlsessionfactory的几个方法基本相同--> <bean id="usermapper" class="org.mybatis.spring.mapper.mapperfactorybean"> <property name="mapperinterface" value="org.mybatis.spring.sample.mapper.usermapper" /> <property name="sqlsessionfactory" ref="sqlsessionfactory" /> </bean>
这样做的缺点是每一个mapper接口都要在xml里配置一下
方法二:采用接口org.apache.ibatis.session.sqlsession的实现类 org.mybatis.spring.sqlsessiontemplate
mybatis中, sessionfactory可由sqlsessionfactorybuilder.来创建。mybatis-spring 中,使用了sqlsessionfactorybean来替代。sqlsessionfactorybean有一个必须属性datasource,另外其还有一个通用属性configlocation(用来指定mybatis的xml配置文件路径)。
sqlsessionfactorybean即相当于原生mybatis中的sqlsessionfactorybuilder
<!-- spring和mybatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource" /> <property name="configlocation" value="classpath:sqlmapconfig.xml"/> <!-- 自动扫描mapping.xml文件,**表示迭代查找,也可在sqlmapconfig.xml中单独指定xml文件--> <property name="mapperlocations" value="classpath:com/hua/saf/**/*.xml" /> </bean> <!-- mybatis spring sqlsessiontemplate,使用时直接让spring注入即可 --> <bean id="sqlsessiontemplate" class="org.mybatis.spring.sqlsessiontemplate"> <constructor-arg index="0" ref="sqlsessionfactory"></constructor-arg> </bean> //使用方法: @repositorypublic class userdao{ @resource private sqlsessiontemplate sqlsessiontemplate; public user getuser(int id) { return sqlsessiontemplate.selectone(this.getclass().getname() + ".getuser", 1); } }
为什么可以这样写,来看一下sqlsessiontemplate
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()); } ........省略...... 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()); } }
如上面代码所示,sqlsessiontemplate类实现了原生mybatis中的sqlsession接口,实际上它就是原生mybatis中的sqlsession
方法三:采用抽象类 org.mybatis.spring.support.sqlsessiondaosupport 提供sqlsession
<!-- spring和mybatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource" /> <property name="configlocation" value="classpath:sqlmapconfig.xml"/> <!-- 自动扫描mapping.xml文件,**表示迭代查找,也可在sqlmapconfig.xml中单独指定xml文件--> <property name="mapperlocations" value="classpath:com/hua/saf/**/*.xml" /> </bean> public class basedao extends sqlsessiondaosupport{ //使用sqlsessionfactory @autowired private sqlsessionfactory sqlsessionfactory; @autowired public void setsqlsessionfactory(sqlsessionfactory sqlsessionfactory) { super.setsqlsessionfactory(sqlsessionfactory); } /** * 执行insert操作 * @param statement * @return */ public int insert(string statement) { return getsqlsession().insert(statement); } /** * 执行insert操作 * @param statement * @param parameter * @return */ public int insert(string statement, object parameter) { return getsqlsession().insert(statement, parameter); } public int update(string statement) { return getsqlsession().update(statement); } public int update(string statement, object parameter) { return getsqlsession().update(statement, parameter); } public int delete(string statement) { return getsqlsession().delete(statement); } public int delete(string statement, object parameter) { return getsqlsession().delete(statement, parameter); } /** * 获取一个list集合 * @param statement * @return */ public list<?> selectlist(string statement) { return getsqlsession().selectlist(statement); } /** * 根据参数 获取一个list集合 * @param statement * @param parameter * @return */ public list<?> selectlist(string statement, object parameter) { return getsqlsession().selectlist(statement, parameter); } public map<?, ?> selectmap(string statement, string mapkey) { return getsqlsession().selectmap(statement, mapkey); } public map<?, ?> selectmap(string statement, object parameter, string mapkey) { return getsqlsession().selectmap(statement, parameter, mapkey); } /** * 获取object对象 * @param statement * @return */ public object selectone(string statement) { return getsqlsession().selectone(statement); } /** * 获取connection, 以便执行较为复杂的用法 * @return */ public connection getconnection() { return getsqlsession().getconnection(); } }
如上代码,一个dao类继承了sqlsessiondaosupport类后,就可以在类中注入sessionfact
ory,进而通过getsqlsession()获取当前sqlsession
下面是 sqlsessiondaosupport的源码 ,它是一个抽象类,并拥有sqlsession属性,在setsqlsessionfactory方法中实例化了该sqlsession:
public abstract class sqlsessiondaosupport extends daosupport { private sqlsession sqlsession; private boolean externalsqlsession; public void setsqlsessionfactory(sqlsessionfactory sqlsessionfactory) { if (!this.externalsqlsession) { this.sqlsession = new sqlsessiontemplate(sqlsessionfactory); } } public void setsqlsessiontemplate(sqlsessiontemplate sqlsessiontemplate) { this.sqlsession = sqlsessiontemplate; this.externalsqlsession = true; } public sqlsession getsqlsession() { return this.sqlsession; } protected void checkdaoconfig() { notnull(this.sqlsession, "property 'sqlsessionfactory' or 'sqlsessiontemplate' are required"); }}
方法四:(也是 最常见的使用方法 ,使用mapperscannerconfigurer,它将会查找类路径下的映射器并自动将它们创建成mapperfactorybean)
由于直接使用mapperfactorybean会在配置文件中配置大量mapper,因此这里使用包扫描的方式通过注解获取该bean
<!-- spring和mybatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean"> <property name="datasource" ref="datasource" /> <!-- 自动扫描mapping.xml文件,**表示迭代查找 --> <property name="mapperlocations" value="classpath:com/hua/saf/**/*.xml" /> </bean> <!-- dao接口所在包名,spring会自动查找其下的类 ,包下的类需要使用@mapperscan注解,否则容器注入会失败 --> <bean class="org.mybatis.spring.mapper.mapperscannerconfigurer"> <property name="basepackage" value="com.hua.saf.*" /> <property name="sqlsessionfactorybeanname" value="sqlsessionfactory" /> </bean> //使用如下代码,即可完成注入 @resource private userdao userdao;
下面看一下mapperscannerconfigurer这个类:
public class mapperscannerconfigurer implements beandefinitionregistrypostprocessor, initializingbean, applicationcontextaware, beannameaware { private string basepackage; private boolean addtoconfig = true; private sqlsessionfactory sqlsessionfactory; private sqlsessiontemplate sqlsessiontemplate; private string sqlsessionfactorybeanname; private string sqlsessiontemplatebeanname; private class<? extends annotation> annotationclass; private class<?> markerinterface; private applicationcontext applicationcontext; private string beanname; private boolean processpropertyplaceholders; private beannamegenerator namegenerator; public void postprocessbeandefinitionregistry(beandefinitionregistry registry) throws beansexception { if (this.processpropertyplaceholders) { processpropertyplaceholders(); } classpathmapperscanner scanner = new classpathmapperscanner(registry); scanner.setaddtoconfig(this.addtoconfig); scanner.setannotationclass(this.annotationclass); scanner.setmarkerinterface(this.markerinterface); scanner.setsqlsessionfactory(this.sqlsessionfactory); scanner.setsqlsessiontemplate(this.sqlsessiontemplate); scanner.setsqlsessionfactorybeanname(this.sqlsessionfactorybeanname); scanner.setsqlsessiontemplatebeanname(this.sqlsessiontemplatebeanname); scanner.setresourceloader(this.applicationcontext); scanner.setbeannamegenerator(this.namegenerator); scanner.registerfilters(); scanner.scan(stringutils.tokenizetostringarray(this.basepackage, configurableapplicationcontext.config_location_delimiters)); } classpathmapperscanner : public set<beandefinitionholder> doscan(string... basepackages) { set<beandefinitionholder> beandefinitions = super.doscan(basepackages); if (beandefinitions.isempty()) { logger.warn("no mybatis mapper was found in '" + arrays.tostring(basepackages) + "' package. please check your configuration."); } else { for (beandefinitionholder holder : beandefinitions) { genericbeandefinition definition = (genericbeandefinition) holder.getbeandefinition(); if (logger.isdebugenabled()) { logger.debug("creating mapperfactorybean with name '" + holder.getbeanname() + "' and '" + definition.getbeanclassname() + "' mapperinterface"); } // the mapper interface is the original class of the bean // but, the actual class of the bean is mapperfactorybean definition.getpropertyvalues().add("mapperinterface", definition.getbeanclassname()); definition.setbeanclass(mapperfactorybean.class); definition.getpropertyvalues().add("addtoconfig", this.addtoconfig); boolean explicitfactoryused = false; if (stringutils.hastext(this.sqlsessionfactorybeanname)) { definition.getpropertyvalues().add("sqlsessionfactory", new runtimebeanreference(this.sqlsessionfactorybeanname)); explicitfactoryused = true; } else if (this.sqlsessionfactory != null) { definition.getpropertyvalues().add("sqlsessionfactory", this.sqlsessionfactory); explicitfactoryused = true; } if (stringutils.hastext(this.sqlsessiontemplatebeanname)) { if (explicitfactoryused) { logger.warn("cannot use both: sqlsessiontemplate and sqlsessionfactory together. sqlsessionfactory is ignored."); } definition.getpropertyvalues().add("sqlsessiontemplate", new runtimebeanreference(this.sqlsessiontemplatebeanname)); explicitfactoryused = true; } else if (this.sqlsessiontemplate != null) { if (explicitfactoryused) { logger.warn("cannot use both: sqlsessiontemplate and sqlsessionfactory together. sqlsessionfactory is ignored."); } definition.getpropertyvalues().add("sqlsessiontemplate", this.sqlsessiontemplate); explicitfactoryused = true; } if (!explicitfactoryused) { if (logger.isdebugenabled()) { logger.debug("enabling autowire by type for mapperfactorybean with name '" + holder.getbeanname() + "'."); } definition.setautowiremode(abstractbeandefinition.autowire_by_type); } } } return beandefinitions; }
总结:spring-mybatis与原生mybatis相比,如下概念:
1)sqlsessionfactory类在两者中都存在
2)前者用sqlsessionfactorybean生成sqlsessionfactory,后者则使用sqlsessionfactorybuilder;
3)前者使用sqlsessiontemplate,后者使用sqlsession,实际上前者实现了后者
4)mapperfactorybean中实现了原生mybatis中下面的步骤,因此通过该类可以直接获取到一个mapper接口的实现对象
employeemapper mapper = session.getmapper(employeemapper.class);
总结
以上所述是小编给大家介绍的spring-mybatis与原生mybatis使用对比分析,希望对大家有所帮助
推荐阅读
-
spring-mybatis与原生mybatis使用对比分析
-
Python参数解析模块sys、getopt、argparse使用与对比分析
-
Mybaits 源码解析 (十)----- 全网最详细,没有之一:Spring-Mybatis框架使用与源码解析
-
与不同框架整合时mybatis的使用区别 (对比activeMQ,见其他类似标题两篇)
-
与不同框架整合时mybatis的使用区别 (对比redis)
-
mybatis的使用及源码分析(一) mybatis介绍以及原生Mybatis项目搭建
-
大势至禁用U口软件、禁止U盘使用软件与同类USB监控软件对比分析
-
Python参数解析模块sys、getopt、argparse使用与对比分析
-
Mybaits 源码解析 (十)----- 全网最详细,没有之一:Spring-Mybatis框架使用与源码解析
-
简单对比分析JavaScript中的apply,call与this的使用_javascript技巧