一、数据源
我门可以使用mybatis自带的数据源,也可以使用外界的数据源,像Ddruid,C3P0,Proxool,这里我用的是C3P0,spring中最主要的是xml配置文件,这里官方建议的是ApplicationContext.xml,我为了方便我门写,我就直接把文件命名为beans.xml,然后通过属性注入的方式注入 C3P0,导入外部数据库连接池需要把Mybatis.xml中自带的数据库连接内容全部删除,代码入下:
<!--数据源 切记去掉Mybatis.xml中的数据源的配置-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/city?characterEncoding=utf8"/>
<property name="user" value="root"/> // 自己数据库的账号
<property name="password" value="123456"/> // 自己数据库的密码
</bean>
二、配置SqlSession工厂
之前如果不通过Spring依赖注入的方式,需要自己手写SqlSession的工厂,代码如下:
public final class MybatisTools {
private static ThreadLocal<SqlSession> th=null;
private static SqlSessionFactory ssf=null;
// 静态加载
static
{
InputStream in=null;
try {
in= Resources.getResourceAsStream("mybatis.xml");
th = new ThreadLocal<SqlSession>();
ssf = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// 获取Sqlsession
public static SqlSession getSqlsession()
{
SqlSession sse = th.get();
if(sse==null)
{
sse = ssf.openSession();
th.set(sse);
}
return sse;
}
// 关闭Sqlsession
public static void closeSqlsession()
{
SqlSession sse = th.get();
if(sse!=null)
{
sse.close();
th.remove();
th.set(null);
}
}
}
现在通过bean注入的话,需要注意两个点,就是,session工厂中的属性datasource,需要ref上面数据源中bean的id,还需要告诉session工厂bean中属性configLocation,他的value需要映射到mybatis.xml,最后一个mapperLocations的值需要映射到具体写sql语句的xml,代码如下:
<!--配置session 工厂 切记去掉 mb.xml 中的映射的配置-->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis.xml"/>
<!--映射文件在哪里-->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
如果这样做就可以把mybatis中关于映射sql语句的xml文件的mappers去掉!
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<mappers>
<mapper resource="UserMapper.xml"></mapper> // 直接去掉
</mappers>
</configuration>
三、配置所有mapper中接口bean
这里需要注意一点的是属性sqlSessionFactoryBeanName中value值必须是上面session工厂的id,如下:
<!--mapper 烧苗 spring 要生成所的mapper bean-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
<!--去哪里扫描 mapper 的接口-->
<property name="basePackage" value="springmybatis.mapper"/>
</bean>
basePackage中的属性需要跟自己项目中具体mapper接口的位置路径一致。
如果配完上面三步基本的增删改查已经没有多大问题了,但是切记我门还需要用到事务。
四、配置事务切面bean
这里标签里面的dataSource需要依赖最开始C3P0的数据源id,这里就已经把spring提供个漆面类配置成bean了,如下:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
然后利用注解,给需要配置事务的方法添上
@Transactional
public void addUser(TbUser user)
如果做到这一步你去给自己的增加数据的业务中手动添加一个异常,如下:
@Override
@Transactional(readOnly = false,timeout = -1,rollbackFor = Exception.class)
public void add(User user) throws Exception{
userMapper.insert(user);
int n = 1/0; // 手动添加异常
userMapper.insert(user);
}
然后你去查看数据库中的内容,你会发现事务并没有回滚,也就是在异常前面执行的插入语句还是插入到了数据库中,这是为什么呢?原来我门不仅需要把spring提供的事务添加成bean,还需要配置事务驱动,还需要添加tx节点,不然是不会有tx标签的,也就是在beans.xml文件中需要添加:
<!--配置事务用注解驱动-->
<tx:annotation-driven></tx:annotation-driven>
<!--切记添加 tx 节点-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
五:事务中的配置
@Transactional(readOnly = false,timeout = -1,rollbackFor = Exception.class)
-
readonly
如果设置为only的话,主要用于查询,如果设置为false用于增删改,不设置的话默认是false
2. timeout
这个是当与数据库建立连接后,如果超过了这个时间还是没有逻辑处理的话,就会自己断开连接,如果设置为-1,就是用数据库的超时时间,
3.rollbackFor
建议将他设置为Exception.class,这样如果手动抛出一个异常还可以将其捕获,事务也会回滚
六、事务传播的行为
@Transactional(propagation = Propagation.REQUIRED)
- 支持当前事务:
- TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。
2. 不支持当前事务:
- TransactionDefinition.PROPAGATION_REQUIRED_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGETION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
3. 其他
- TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。