一、SM思路分析

1、引入核心依赖及相关依赖:

 spring(略)、mybatis、mysql、mybatis-spring(减少自己实现FactoryBean接口)、druid

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.5</version>
</dependency>

2、如何整合?

通过spring框架接管mybatis框架中核心对象的创建

3、mybatis中的核心对象

SqlSessionFactory

4、SM整合实质

通过spring框架接管mybatis中核心的SqlSessionFactory对象的创建。Spring如何管理SqlSessionFactory对象的创建?SqlSessionFactory是一个接口类型的复杂对象。

is=Resource.getResourceAsStrem("mybatis-config.xml);

sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);

1)手动配置:

(0)在类路径下配置mybatis-config.xml的数据源:

<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="xroot"/>
</dataSource>

(1)在spring中可以新建类SqlSessionFactoryBean实现FactoryBean接口

//自定义SqlSessionFactory
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory> {
private String configLocations;//通过参数注入配置文件名 public void setConfigLocations(String configLocations) {
this.configLocations = configLocations;
} public SqlSessionFactory getObject() throws Exception {
//InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
InputStream rs = Resources.getResourceAsStream(configLocations);
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(rs);
return build;
} public java.lang.Class<?> getObjectType() {
return SqlSessionFactory.class;
} public boolean isSingleton() {
return true;
}
}

(2)工厂管理SqlSessionFactory

<bean id="sqlSessionFactory" class="com.icucoder.SqlSessionFactoryBean">
<property name="configLocations" value="mybatis-config.xml"/>
</bean>

(3)工厂获取

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
System.out.println(sqlSessionFactory.openSession());

2)spring自动配置(使用mybatis-spring依赖:Mybatis-spring.jar封装了SqlSessionFactory对象的创建)

(0)加入mybatis-spring依赖、druid依赖(简单类型)

(1)工厂管理SqlSessionFactory并配置druid数据源对象dataSource

<!--创建数据源对象 druid c3p0 dbcp-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="xroot"/>
</bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--依赖数据源-->
<property name="dataSource" ref="dataSource"/>
<!--依赖mapper文件注册-->
<property name="mapperLocations">
<array>
<value>com/icucoder/mapper/UserDaoMapper.xml</value>
</array>
</property>
</bean>

上述配置每创建一个Mapper文件,需要配置一个array,可以使用mapperLocations配置某个具体类路径下xml的自动扫描。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 依赖数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 注入mapper通用方式 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<!-- 取别名 -->
<property name="typeAliasesPackage" value="com.icucoder.entity"></property>
</bean>
 

(2)工厂获取

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
System.out.println(sqlSessionFactory.openSession());

二、DAO层开发

1、建实体类(前提数据库中有表)

public class User {
private Integer id;
private String name;
private Integer age;
private Integer email;
//省略有参和无参构造 setter和getter方法
}

2、DAO接口

public interface UserDao {
List<User>findAll();
}

3、开发mapper(dao的实现类)

<mapper namespace="com.icucoder.dao.UserDao">
<select id="findAll" resultType="com.icucoder.entity.User">
select id,name,age,email
from user
  </select>
</mapper>

4、spring配置文件中注册mapper配置文件

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--依赖数据源-->
<property name="dataSource" ref="dataSource"/>
<!--依赖mapper文件注册-->
<property name="mapperLocations">
<array>
<value>classpath:mapper/UserDaoMapper.xml</value>
</array>
</property>
</bean>

上述配置每创建一个Mapper文件,需要配置一个array,可以使用mapperLocations配置某个具体类路径下xml的自动扫描(见上)。

5、启动工厂获SqlSessionfactory

1)手动获取DAO:

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean("sqlSessionFactory");
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
System.out.println(userDao.findAll());

2)使用MapperFactoryBean获取DAO:

(1)在MapperFactoryBean中注入SqlSessionFactory和Dao路径

<!--创建Dao组件类-->
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--注入dao类型-->
<property name="mapperInterface" value="com.icucoder.dao.UserDao"/>
</bean>

上述配置每创建一个Dao组件类,需要配置一个bean,可以使用MapperScannerConfigurer配置某个具体累计下dao的自动扫描

<!--创建Dao组件类-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>>
<!--扫描DAO接口所在包-->
<property name="basePackage" value="com.icucoder.dao"/>
</bean>

(2)调用bean

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao = (UserDao) context.getBean("userDao");
System.out.println(userDao.findAll());

三、Service层事务控制

在上述dao的基础上:

1、常规做法(使用默认的事务)

1)创建Service及其实现类

//UserService省略
public class UserServiceImpl implements UserService {
private UserDao userDao;
//private DataSource dataSource;//手动注入 dataSoruce无法保证service与dao层事务的连接性
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
} @Override
public List<User> findAll() {
return userDao.findAll();
}
}

2)在spring配置文件中管理service组件

<bean id="userService" class="com.icucoder.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>

3)调用Bean

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService.findAll());

2、mybatis框架中事物控制分析

SqlSession,提交:sqlSession.commit);回滚:sqlSessioin.rollback();

真正负责数据库事物控制的对象:Connection(java.sql.Connection)对象。

注意:数据源DruidDataSource是一个连接池,里面都是Connection对象。

Connection conn=DruidDataSource().getConnection();

可以在业务层手动注入dataSource对象来控制事务,但是无法保证业务层(Sevice)和Dao事务的连接性。

3、数据源事务管理器:DataSourceTransactionManager

在spring和mybatis框架中提供了一个类DataSourceTransactionManager(数据源事务管理器)来全局创建一个事务管理器,用来统一调度业务层当前线程使用连接对象和DAO层实现连接对象一致。它依赖于数据源。

在spring.xml文件中添加DataSourceTransactionManager的bean。

<!---数据源事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

4、给现有业务层加入事务控制(手动配置事务)

1)重写service实现类

public class UserServiceImpl implements UserService {
private PlatformTransactionManager transactionManager; public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
} private UserDao userDao; public void setUserDao(UserDao userDao) {
this.userDao = userDao;
} @Override
public List<User> findAll() {
return userDao.findAll();
} @Override
public void save(User user) {
TransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(transactionDefinition); //控制事物
try {
//处理业务
//调用业务
userDao.save(user);
int i=1/0;
transactionManager.commit(status);
System.out.println("save success");
}catch (Exception e){
e.printStackTrace();
transactionManager.rollback(status);
}
}
}

2)在spring配置文件的service的bean标签中注入数据源事务管理器

<bean id="userService" class="com.icucoder.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>

3)调用Bean

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
User user=new User(7,"test",12,"admin@qq.com");
System.out.println(user);
userService.save(user);

四、Service层事务控制优化(自动配置事务)

1、spring中处理事务的两种方式

编程式事务处理:通过在业务层中农注入事务管理器对象,然后通过编码的方式进行事务控制。

声明式事务处理:通过利用aop切面编程进行事务控制,并对事务属性在配置文件中完成细粒度配置。

2、给现有业务层加入事务控制(手动配置事务优化)

开发一个基于事务的通知(环绕通知)TransactionAdvice实现MethodInterceptor。

1)创建环绕通知

2)配置切面

3)使用环绕通知

3、给现有业务层加入事务控制(自动配置事务-使用aop)

spring框架提供了<tx:advice/>标签,该标签可以根据事务管理器创建一个基于事务环绕通知对象,并对业务层方法进行细粒度事务控制。

1)在spring配置文件中加入声明式事务管理

<!--声明式事务管理-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--事务细粒度控制,不控制则事务不生效-->
<tx:attributes>
<tx:method name="save*"/>
</tx:attributes>
</tx:advice>

2)配置切面

<!--配置事务切面-->
<aop:config>
<aop:pointcut id="pc" expression="within(com.icucoder.service.impl.*ServiceImpl)"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/>
</aop:config>

3)重写service实现类

public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
this.userDao = userDao;
} @Override
public List<User> findAll() {
return userDao.findAll();
} @Override
public void save(User user) {
//控制事物
//处理业务
//调用业务
userDao.save(user);
int i = 1 / 0;
System.out.println("save");
}
}

4、给现有业务层加入事务控制(自动配置事务-开启注解式事务驱动管理器)

1)在spring配置文件中加入tx:annotation-driven,这样就不要<tx:advice/>和<aop:config>,可以直接使用注解@Transactional。

<!--开启注解式事务驱动管理器@Transactional-->
<tx:annotation-driven transaction-manager="transactionManager"/>

2)重写service实现类

@Transactional
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) {
this.userDao = userDao;
} @Override
public List<User> findAll() {
return userDao.findAll();
} @Override
public void save(User user) {
//控制事物
//处理业务
//调用业务
userDao.save(user);
int i = 1 / 0;
System.out.println("save"); }
}
 注:
也可以使用easycode直接对数据的表生成entity,controller,service,dao,mapper,无需任何编码。
 

Spring入门二:整合mybatis的更多相关文章

  1. Spring Boot:整合MyBatis框架

    综合概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单 ...

  2. MyBatis原理,Spring、SpringBoot整合MyBatis

    1. MyBatis概述 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可 ...

  3. spring boot 2整合mybatis

    mybatis-spring-boot-starter主要有两种解决方案,一种是使用注解,一种是使用XML. 参考这篇文章动手跑了一个例子,稍微不同之处,原文是spring boot,这里改成了spr ...

  4. springboot(二)整合mybatis,多数据源和事务管理

     -- 1.整合mybatis -- 2.整合多数据源 -- 3. 整合事务 代码地址:https://github.com/showkawa/springBoot_2017/tree/master/ ...

  5. Spring入门(二):自动化装配bean

    Spring从两个角度来实现自动化装配: 组件扫描(component scanning):Spring会自动发现应用上下文中需要创建的bean. 自动装配(autowiring):Spring会自动 ...

  6. Spring Boot 应用系列 3 -- Spring Boot 2 整合MyBatis和Druid,多数据源

    本文演示多数据源(MySQL+SQL Server)的配置,并且我引入了分页插件pagehelper. 1. 项目结构 (1)db.properties存储数据源和连接池配置. (2)两个数据源的ma ...

  7. Spring Boot2 系列教程(二十二)整合 MyBatis 多数据源

    关于多数据源的配置,前面和大伙介绍过 JdbcTemplate 多数据源配置,那个比较简单,本文来和大伙说说 MyBatis 多数据源的配置. 其实关于多数据源,我的态度还是和之前一样,复杂的就直接上 ...

  8. 10、Spring教程之整合MyBatis

    1.步骤 1.导入相关jar包 junit <dependency> <groupId>junit</groupId> <artifactId>juni ...

  9. SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件

    原文链接 我们这一篇博客讲的是如何整合Springboot和Mybatis框架,然后使用generator自动生成mapper,pojo等文件.然后再使用阿里巴巴提供的开源连接池druid,这个连接池 ...

随机推荐

  1. Java 继承02

    向上类型转换 父类型的引用指向子类型的实例. Person p = new Person();Animal a = p; //子类对象赋值给父类类型的变量 注意: 向上转型后,子类单独定义的方法会丢失 ...

  2. cloudcompare备忘录(1)

    1.找点 然后直接在需要的位置上点就会出现这个点的信息了~! 2.想看一个三d的切面时候 先选中切的目标 点击小剪刀~ 点击鼠标左键四次来框选,然后点击鼠标右键确认 再点击这个按钮就切好了

  3. 布客&#183;ApacheCN 翻译/校对/笔记整理活动进度公告 2020.1

    注意 请贡献者查看参与方式,然后直接在 ISSUE 中认领. 翻译/校对三个文档就可以申请当负责人,我们会把你拉进合伙人群.翻译/校对五个文档的贡献者,可以申请实习证明. 请私聊片刻(52981514 ...

  4. 【第十二期】腾讯后台实习初试、复试、HR面经 (许愿OC)

    楼主投的很晚属于正常批才开始,初试面试官比较重基础,复试面试官比较看综合能力,HR小姐姐声音好听,腾讯面试官都特别nice! 一面: 看你项目很多,你挨个给我介绍一遍吧 我:一大堆按着简历介绍 日志文 ...

  5. 【源码】Redis exists命令bug分析

    本文基于社区版Redis 4.0.8 1.复现条件 版本:社区版Redis 4.0.10以下版本 使用场景:开启读写分离的主从架构或者集群架构(master只负责写流量,slave负责读流量) 案例: ...

  6. C语言非阻塞式键盘监听

    监听键盘可以使用C语言的字符输入函数,例如 getchar.getch.getche 等,使用getche函数监听键盘的例子: #include <stdio.h> #include &l ...

  7. ittun.com的使用方法

    [如果这篇文章对你有所作用,请加关注哦!] 步骤一: 进入官网http://ittun.com/ Windows 64位下载http://ittun.com/upload/17.2/ittun_win ...

  8. 利用ICMP协议的PING命令获取客户端当前网络质量 by徐文棋

    无论在windows下,linux也好,unix也好,都可以通过 Ping命令获得当前设备的网络延迟,延迟是客户端到服务端的网络响应时间.通常延迟越低,反应速度越快 这里使用了SimplePing   ...

  9. 索引,事务,存储引擎和选择,视图,mysql管理

    一.mysql索引:提高数据库的性能(不用加内存,不用改程序,不用调sql,查询速度就可能提高百倍千倍)索引会占用磁盘空间 CREATE   INDEX   索引名   ON   数据表 (列名or字 ...

  10. Docker磁盘空间分析与清理

    首先使用du命令逐层分析docker磁盘的使用情况: (base) [root@openvino docker]# du -h --max-depth=1 | sort 0 ./containerd ...