Spring入门二:整合mybatis
一、SM思路分析
1、引入核心依赖及相关依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | < 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的数据源:
1 2 3 4 5 6 | < 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&serverTimezone=UTC"/> < property name="username" value="root"/> < property name="password" value="xroot"/> </ dataSource > |
(1)在spring中可以新建类SqlSessionFactoryBean实现FactoryBean接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //自定义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
1 2 3 | <bean id= "sqlSessionFactory" class = "com.icucoder.SqlSessionFactoryBean" > <property name= "configLocations" value= "mybatis-config.xml" /> </bean> |
(3)工厂获取
1 2 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!--创建数据源对象 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的自动扫描。
1 2 3 4 5 6 7 8 9 | <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)工厂获取
1 2 3 | ApplicationContext context = new ClassPathXmlApplicationContext( "spring.xml" ); SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) context.getBean( "sqlSessionFactory" ); System.out.println(sqlSessionFactory.openSession()); |
二、DAO层开发
1、建实体类(前提数据库中有表)
1 2 3 4 5 6 7 | public class User { private Integer id; private String name; private Integer age; private Integer email; //省略有参和无参构造 setter和getter方法 } |
2、DAO接口
1 2 3 | public interface UserDao { List<User>findAll(); } |
3、开发mapper(dao的实现类)
1 2 3 4 5 6 | < 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配置文件
1 2 3 4 5 6 7 8 9 10 | < 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:
1 2 3 4 5 | 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路径
1 2 3 4 5 6 | <!--创建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的自动扫描
1 2 3 4 5 6 | <!--创建Dao组件类--> <bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name= "sqlSessionFactoryBeanName" value= "sqlSessionFactory" />> <!--扫描DAO接口所在包--> <property name= "basePackage" value= "com.icucoder.dao" /> </bean> |
(2)调用bean
1 2 3 | ApplicationContext context = new ClassPathXmlApplicationContext( "spring.xml" ); UserDao userDao = (UserDao) context.getBean( "userDao" ); System.out.println(userDao.findAll()); |
三、Service层事务控制
在上述dao的基础上:
1、常规做法(使用默认的事务)
1)创建Service及其实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 | //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组件
1 2 3 | <bean id= "userService" class = "com.icucoder.service.impl.UserServiceImpl" > <property name= "userDao" ref= "userDao" /> </bean> |
3)调用Bean
1 2 3 | 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。
1 2 3 4 | <!---数据源事务管理器--> <bean id= "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name= "dataSource" ref= "dataSource" /> </bean> |
4、给现有业务层加入事务控制(手动配置事务)
1)重写service实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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标签中注入数据源事务管理器
1 2 3 4 | < bean id="userService" class="com.icucoder.service.impl.UserServiceImpl"> < property name="userDao" ref="userDao"/> < property name="transactionManager" ref="transactionManager"/> </ bean > |
3)调用Bean
1 2 3 4 5 | 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配置文件中加入声明式事务管理
1 2 3 4 5 6 7 | <!--声明式事务管理--> <tx:advice id= "txAdvice" transaction-manager= "transactionManager" > <!--事务细粒度控制,不控制则事务不生效--> <tx:attributes> <tx:method name= "save*" /> </tx:attributes> </tx:advice> |
2)配置切面
1 2 3 4 5 | <!--配置事务切面--> <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实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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。
1 2 | <!--开启注解式事务驱动管理器@Transactional--> < tx:annotation-driven transaction-manager="transactionManager"/> |
2)重写service实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @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" ); } } |
![](https://img2020.cnblogs.com/blog/604038/202107/604038-20210711170007947-1179125124.png)
如果你真心觉得文章写得不错,而且对你有所帮助,那就不妨小小打赏一下吧,如果囊中羞涩,不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
![qq群](https://files-cdn.cnblogs.com/files/hoaprox/qqqun.bmp)
![微信](https://files.cnblogs.com/files/hoaprox/zsm.bmp)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· 本地部署 DeepSeek:小白也能轻松搞定!
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
2016-03-25 ORACLE之表
2016-03-25 ORACLE之PACKAGE-游标变量