原生mybatis使用方法:
1
2
3
4
5
6
7
8
9
10
11
12
|
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使用方法,直接注入即可
1
2
|
@Autowired
EmployeeMapper employeeMapper
|
那么spring为我们做了什么?下面研究一下mybatis-spring.jar这个jar包
首先来看一下如何使用spring整合mybatis,下面是使用spring-mybatis的四种方法:
方法一:(使用MapperFactoryBean)
1
2
3
4
5
6
7
8
9
10
11
|
<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
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- 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
1
2
3
4
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<!-- 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!-- 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这个类:
1
2
3
4
|
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接口的实现对象
1
|
EmployeeMapper mapper = session.getMapper(EmployeeMapper. class );
|
总结
以上所述是小编给大家介绍的spring-mybatis与原生mybatis使用对比分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:https://www.tuicool.com/articles/AN7NfiE