12. 整合Mybatis
步骤:
-
导入相关jar包
-
junit
-
mybatis
-
sql数据库
-
spring相关的
-
aop织入
-
mybatis-spring【new】
(注意!!这里的spring-core包要和spring-jdbc包的版本一致!!!!否则报错java.lang.NoSuchMethodError: org.springframework.beans.factory.config.ConfigurableListableBeanFactor)
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.16</version> </dependency> <!--Spring操作数据库的话,还需要spring-jdbc这个包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.6</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.3.6</version> </dependency> </dependencies>
-
-
编写配置文件
-
测试
12.1 回忆MyBatis
-
编写实体类
@Data public class User { private int id; private String name; private String pwd; }
-
编写核心配置文件
<?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> <typeAliases> <package name="com.Yurrize.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306"/> <property name="username" value="root"/> <property name="password" value="020113"/> </dataSource> </environment> </environments> <mappers> <mapper class="com.Yurrize.mapper.UserMapper"/> </mappers> </configuration>
-
编写接口
public interface UserMapper { public List<User> selectUser(); }
-
编写mapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.Yurrize.mapper.UserMapper"> <select id="selectUser" resultType="User"> select * from mybatis.user </select> </mapper>
-
测试
public class MyTest { @Test public void test() throws IOException { String resources="mybatis-config.xml"; InputStream stream = Resources.getResourceAsStream(resources); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream); SqlSession sqlSession = sqlSessionFactory.openSession(true); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.selectUser(); for (User user : userList) { System.out.println(user); } } }
12.2 MyBatis-Spring
-
什么是MyBatis-Spring
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和
SqlSession
并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的DataAccessException
。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
-
编写数据源配置
- 核心配置文件:代替原来的mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--DataSource:使用Spring的数据源替换Mybatis的配置 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="020113"/> </bean> <!--sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!--绑定mybatis配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/Yurrize/mapper/*.xml"/> </bean> <!--SqlSessionTemplate:就是我们使用的sqlSession--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--只能使用构造器注入sqlSessionFactor,因为没有set方法--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> </beans>
- 在原来的mybatis文件中保留别名,与设置等标签,当然也可以整合到核心文件中
<?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> <typeAliases> <package name="com.Yurrize.pojo"/> </typeAliases> <setting.......></setting.......> </configuration>
- 将实现类的bean分离出来,便于阅读
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <import resource="spring-dao.xml"/> <bean id="userMapper" class="com.Yurrize.mapper.UserMapperImpl"> <property name="sqlSessionTemplate" ref="sqlSession"/> </bean> </beans>
-
sqlSessionFactory
<!--sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!--绑定mybatis配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/Yurrize/mapper/*.xml"/> </bean>
-
sqlSessionTemplate
<!--SqlSessionTemplate:就是我们使用的sqlSession--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--只能使用构造器注入sqlSessionFactor,因为没有set方法--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean>
-
需要给接口添加实现类【新增】
public class UserMapperImpl implements UserMapper{ //在原来我们所有操作都是用sqlSession来执行,现在使用sqlSessionTemplate private SqlSessionTemplate sqlSessionTemplate; public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } @Override public List<User> selectUser() { UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class); return mapper.selectUser(); } }
-
将自己写的实现类注入到Spring中测试
public class MyTest { @Test public void test() throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); for (User user : userMapper.selectUser()) { System.out.println(user); } } }
12.3 SqlSessionDaoSupport
SqlSessionDaoSupport
是一个抽象的支持类,用来为你提供 SqlSession
。调用 getSqlSession()
方法你会得到一个 SqlSessionTemplate
,之后可以用于执行 SQL 方法,就像下面这样:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
在这个类里面,通常更倾向于使用 MapperFactoryBean
,因为它不需要额外的代码。但是,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一个非抽象的实现类,那么这个类就很有用了。
SqlSessionDaoSupport
需要通过属性设置一个 sqlSessionFactory
或 SqlSessionTemplate
。如果两个属性都被设置了,那么 SqlSessionFactory
将被忽略。
假设类 UserMapperImpl
是 SqlSessionDaoSupport
的子类,可以编写如下的 Spring 配置来执行设置:
<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
13. 声明式事务
13.1 回顾事务
- 把一组事务当初一个业务来做,要么都成功,要么都失败
- 事务在项目开发中,涉及到数据一致性问题
- 确保完整性和一致性
事务的ACID原则:
- 原子性:确保事务要不都成功,要不都失败
- 一致性:一旦事务完成,要么一致提交,数据前后保持不变
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,但要排除其他事务对本次事务的影响
- 持久性:事务一旦提交,无论系统发生什么问题,结果不会被影响,被持久化的写到存储器中
13.2 Spring中的事务管理
- 声明式事务:Aop
- 编程式事务:需要在代码中运行事务管理
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<!--结合AOP,实现事务的织入-->
<!--配置事务的类-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--给哪些方法配置事务-->
<!--配置事务的传播特性:new-->
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.Yurrize.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况下;
- 如果我们不在Spring中配置声明式事务,我们就需要在代码中手动配置事务
- 事务在项目开发中十分重要,涉及到数据的一致性和完整性问题
essionTemplate。如果两个属性都被设置了,那么
SqlSessionFactory` 将被忽略。
假设类 UserMapperImpl
是 SqlSessionDaoSupport
的子类,可以编写如下的 Spring 配置来执行设置:
<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
13. 声明式事务
13.1 回顾事务
- 把一组事务当初一个业务来做,要么都成功,要么都失败
- 事务在项目开发中,涉及到数据一致性问题
- 确保完整性和一致性
事务的ACID原则:
- 原子性:确保事务要不都成功,要不都失败
- 一致性:一旦事务完成,要么一致提交,数据前后保持不变
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,但要排除其他事务对本次事务的影响
- 持久性:事务一旦提交,无论系统发生什么问题,结果不会被影响,被持久化的写到存储器中
13.2 Spring中的事务管理
- 声明式事务:Aop
- 编程式事务:需要在代码中运行事务管理
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<!--结合AOP,实现事务的织入-->
<!--配置事务的类-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--给哪些方法配置事务-->
<!--配置事务的传播特性:new-->
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.Yurrize.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况下;
- 如果我们不在Spring中配置声明式事务,我们就需要在代码中手动配置事务
- 事务在项目开发中十分重要,涉及到数据的一致性和完整性问题