您的位置:首页 > 编程语言 > Java开发

MyBatis-Spring官方文档 学习笔记

2017-10-31 00:33 579 查看

前言

之前也写过
SpringMVC
+
MyBatis
+
Spring
的小项目,但是对
MyBatis
的了解还是不够深入,配置也只会生搬硬套。刚好求职失败,遂有空,去阅读以下
MyBatis-Spring
的官方文档,深入学习一波。

什么是MyBatis-Spring?

MyBatis-Spring
就是帮助你将
MyBatis
代码无缝的整合到
Spring
中。
Spring
将会加载必要的
sqlSessionFactory
类和
session
类。

配置数据源

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:app.properties</value>
</list>
</property>
</bean>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>

<property name="maxPoolSize" value="20" />
<property name="minPoolSize" value="5" />
<property name="acquireIncrement" value="3" />
<property name="initialPoolSize" value="5"></property>
</bean>


配置SqlSessionFactory

我们需要在Spring应用上下文定义一个
SqlSessionFactory
和数据源
dataSource
。在
MyBatis-Spring
中,
SqlSessionFacotoryBean
调用其
getObject()
方法去创建
SqlSessionFactory
实例。创建
SqlSessionFactory
实例中用到了享元设计模式,是一个种结构型模式。

享元模式(Flyweight Pattern):主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了极少对象数量从而改善应用所需的对象结构的方式。

优点:大大减少对象的创建,降低系统的内存,提供效率。

缺点: 提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部的状态而改变,否则会造成系统的混乱。

言归正传,首先在这个
SqlSessionFactoryBean
类中,调用
getObject()
时,会判断
sqlSessionFacotory
是否为空,如果不为空直接返回
sqlSessionFacotory
。如果为空,则调用
afterPropertiesSet()
方法。

public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
return this.sqlSessionFactory;
}


afterPropertiesSet()
会检查
dataSource
sqlSessionFactoryBuilder
是否为空。接着会调用
buildSqlSessionFactory()
方法。

public void afterPropertiesSet() throws Exception {
notNull(dataSource, "Property 'dataSource' is required");
notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");

this.sqlSessionFactory = buildSqlSessionFactory();
}


buildSqlSessionFactory()
方法会读取
xml
配置,然后创建
sqlSessionFactory
实例。

protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
//...省略几百行代码
return this.sqlSessionFactoryBuilder.build(configuration);
}


言归正传,配置如下:

mapperLocations
: 我们存放
MyBatis
mapper.xml
文件路径。

typeAliasesPackage
:一般对应着我们实体类所在的包。多个
package
之间可以用逗号或者分号等来进行分隔。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.helping.wechat.model"></property>
<property name="mapperLocations" value="classpath*:com/helping/wechat/model/**/mysql/*Mapper.xml" />
</bean>


事务

一个使用
MyBatis-Spring
的主要原因是它允许
MyBatis
参与到
Spring
的事务管理中,而不是给
MyBatis
创建一个新的事务管理器。
MyBatis-Spring
利用了存在
Spring
中的
org.springframework.jdbc.datasource.DataSourceTransactionManager
。我们可以通过配置
<tx:annotation-driven transaction-manager="transactionManager"/
>来使用
@Transactional
注解面对切面编程。同时我们也可以通常的
AOP
来配置Service层的事务。在事务处理期间,一个单独的
SqlSession
对象将会被创建和使用,当事务完成时,这个
Session
就会以合适的方式进行提交和回滚。具体配置如下:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 当Service层的方法不是以delete,insert,update,save方法开头时,发生异常时无法进行事务回滚
但是可以通过@Transactional注解在类或者方法上,可以启动事务。
-->
<tx:annotation-driven transaction-manager="transactionManager"/>

<!-- 任何RuntimeException将触发事务回滚,但是任何Checked Exception不会触发事务回滚 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<t
f7a8
x:method name="delete*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="insert*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="save*" propagation="REQUIRED" read-only="false" isolation="DEFAULT"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut expression="execution(* com.helping.wechat.service..*.*(..))" id="pc"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc" order="1"/>
</aop:config>


使用SqlSession

MyBatis
中,我们可以使用
SqlSessionFactory
来创建
SqlSession
。一旦获得了一个
session
之后,我们可以使用它来执行映射语句,提交或者回滚。当我们不需要它的时候,我们可以关闭
session


而在
MyBatis-Spring
之后,你不再需要
SqlSessionFactory
了,我们的
Dao
层可以注入一个线程安全的
SqlSession
,然后进行提交或者回滚,最后关闭
session


SqlSession Template

SqlSession Template
MyBatis-Spring
的核心,这个类负责
MyBatis
SqlSession


this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);


我们可以知道
SqlSessionTemplate
类的构造器第一个参数是
SqlSessionFactory
的实例。
SqlSessionTemplate
实现了
SqlSession
接口。

public class SqlSessionTemplate implements SqlSession {
//...省略n行
}


之前的我是这样配置的:

<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

<bean id="baseDao" abstract="true">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate" />
</bean>

<bean id="adminUserDao" class="com.helping.wechat.dao.admin.mybatis.AdminUserDao" parent="baseDao" />


其实没有必要去
Spring.xml
去配置
Dao
层,
Service
层,
Controller
类。可以用注解代替,后面会讲到。对了,
SqlSessionTemplate
其实也不需要配,
SqlSession
我们可以通过
new SqlSessionTemplate()
创建出来。

SqlSessionDaoSupport

SqlSessionDaoSupport
是一个抽象的支持类,为你提供
SqlSession
。我们自定义的
Dao
层的实现类继承它就行了。调用
getSession()
做你想要的。
SqlSessionDaoSupport
内部实现:

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;
}

/**
* Users should use this method to get a SqlSession to call its statement methods
* This is SqlSession is managed by spring. Users should not commit/rollback/close it
* because it will be automatically done.
*
* @return Spring managed thread safe SqlSession
* 返回线程安全的sqlSession
*/
public SqlSession getSqlSession() {
return this.sqlSession;
}

/**
* {@inheritDoc}
*/
protected void checkDaoConfig() {
notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}


看到
getSession()
方法的注释写着,用户不应该去提交,回滚,或者关闭
session
的操作,因为
session
会自动关闭它。这个方法返回的是一个线程安全的
sqlSession


使用注解代替XML的配置

如果不使用注解,你的
Spring.xml
配置肯定是多的爆炸,比如这样:

<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

<bean id="baseDao" abstract="true">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate" />
</bean>

<bean id="adminUserDao" class="com.helping.wechat.dao.admin.mybatis.AdminUserDao" parent="baseDao" />

<bean id="adminUserService" class="com.helping.wechat.service.admin.impl.AdminUserService" >
<property name="adminUserDao" ref="adminUserDao" />
</bean>

<bean id="adminUserController" class="com.helping.wechat.controller.admin.AdminUserController" >
<property name="adminUserService" ref="adminUserService" />
</bean>

<bean id="ordinaryUserDao" class="com.helping.wechat.dao.admin.mybatis.OrdinaryUserDao" parent="baseDao" />

<bean id="ordinaryUserService" class="com.helping.wechat.service.admin.impl.OrdinaryUserService" >
<property name="ordinaryUserDao" ref="ordinaryUserDao" />
</bean>

<bean id="ordinaryUserController" class="com.helping.wechat.controller.admin.OrdinaryUserController" >
<property name="ordinaryUserService" ref="ordinaryUserService" />
</bean>


如果使用了
@Service
@Component
@Repository
@Controller
@Resource
@Autowired
这些注解,这些配置统统可以不要。首先要在
SpringMVC.xml
配置自动扫描注解的
tag


<context:component-scan base-package="com.helping.wechat.controller" />
<context:component-scan base-package="com.helping.wechat.handler" />
<context:component-scan base-package="com.helping.wechat.dao" />
<context:component-scan base-package="com.helping.wechat.service" />


@Service
用于标注业务
Service
层的类上,有
value
这个属性。

@Service(value = "adminUserService")
public class AdminUserService implements IAdminUserService {

@Resource(name = "adminUserDao")
private IAdminUserDao adminUserDao;
}


@Controller
用于标注控制
Controller
层的类上。

@Controller
@RequestMapping("/api/admin")
public class AdminUserController extends BaseController {

@Resource(name = "adminUserService")
private IAdminUserService adminUserService;
}


@Repository
用于标注在
Dao
层的类上,有
value
这个属性。

@Repository(value = "adminUserDao")
public class AdminUserDao extends SqlSessionDaoSupport implements IAdminUserDao {

}


@Component
就是把类注册到
Spring.xml
文件中。

@Component
public abstract class BaseDao {
protected SqlSession sqlSession;

protected SqlSessionFactory sqlSessionFactory;

@Resource(name = "sqlSessionFactory")
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);}

public void setSqlSession(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}

public SqlSession getSqlSession() {
return sqlSession;
}
}


Dao
层的类继承它就行了,就可以调用
getSqlSession()
进行想要的操作了。

@Resource
默认按名称进行装配字段或者
setter
方法。名称可以通过
name
属性进行指定,如果没有指定
name
属性。当注解写在字段上,默认按字段名进行安装名称查找,如果注解写在
setter
方法上,默认按属性名进行装配,当找不到与名称相匹配的
bean
时候,才会按照类型进行装配。如果
name
属性指定了,那么就只能按名称进行装配了。

@Service(value = "adminUserService")
public class AdminUserService implements IAdminUserService {

@Resource(name = "adminUserDao")
private IAdminUserDao adminUserDao;
}


@Autowired
:默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要运行
null
值,可以设置它的
required
属性为
false
。如果我们想要使用名称进行装配,可以结合
@Qualifier
注解使用。

@Autowired
public void setAdminUserService(IAdminUserService adminUserService) {
this.adminUserService = adminUserService;
}


尾言

明天去看看通用
Mapper
pageHelper
怎么配置。晚安,地球人。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: