欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring-mybatis与原生mybatis使用对比分析

程序员文章站 2024-04-01 20:01:04
原生mybatis使用方法: string resource = "mybatis-config.xml"; inputstream inputstream...

原生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使用对比分析,希望对大家有所帮助