目录
(4)MyBatis参数配置——>SqlMapConfig.xml
本章学习源码Github地址:https://github.com/GuiZhouAndroid/MySpringAllProject/tree/master/SpringDemo10_Spring_Mybatis_SM
将MyBatis与Spring进行整合,主要解决的问题就是将SqlSessionFactory对象交由Spring来管理 。所以 ,该整合只需要将SqlSessionFactory的对象生成器SqlSessionFactoryBean注册在Spring容器中,再将其注入给Dao的实现类即可完成整合。实现Spring与MyBatis的整合。常用的方式:扫描的Mapper动态代理。Spring 像插线板一样,mybatis框架是插头,可以容易的组合到一起。插线板spring插上mybatis,两个框架就是一个整体。
说明:创建两张简单表,后面为方便实践演示AOP与事务的关联。
- CREATE TABLE accounts (
- `aid` int PRIMARY KEY,
- `aname` varchar(20),
- `acontent` varchar(50)
- );
-
- CREATE TABLE users (
- `userid` int PRIMARY KEY,
- `uname` varchar(20),
- `upass` varchar(20)
- );
(1)AspectJ:使用切面框架,完成AOP和事务的处理细节。
(2)Spring:使用Spring容器相关整合必需。
(3)MyBatis:数据访问层映射使用到数据持久内部封装JDBC的框架
(4)MySQL:通过Mybatis内部JDBC支持的数据源,依照MySQL官方向外定制连接协议和规范,通过端口号3306与本地设备MySQL服务中的数据库建立连接,最终执行CRUD操作表数据。
(5)Druid:更高效的数据库连接池,替代Mybatis的数据源(Druid连接MySQL)
- <dependencies>
- <!--单元测试-->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.13.2</version>
- <scope>test</scope>
- </dependency>
- <!--aspectj依赖-->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>5.3.21</version>
- </dependency>
- <!--spring核心ioc-->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>5.3.21</version>
- </dependency>
- <!--做spring事务用到的-->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>5.3.21</version>
- </dependency>
- <!--做spring的JDBC-->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jdbc</artifactId>
- <version>5.3.21</version>
- </dependency>
- <!--mybatis依赖-->
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis</artifactId>
- <version>3.5.10</version>
- </dependency>
- <!--mybatis和spring集成的依赖-->
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis-spring</artifactId>
- <version>2.0.7</version>
- </dependency>
- <!--mysql驱动-->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>8.0.29</version>
- </dependency>
- <!--阿里公司的数据库连接池-->
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid</artifactId>
- <version>1.2.11</version>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <!-- 扫描加载java目录下指定后缀资源 -->
- <resource>
- <directory>src/main/java</directory>
- <includes>
- <include>**/*.xml</include>
- <include>**/*.properties</include>
- </includes>
- </resource>
- <!-- 扫描加载resources目录下指定后缀资源 -->
- <resource>
- <directory>src/main/resources</directory>
- <includes>
- <include>**/*.xml</include>
- <include>**/*.properties</include>
- </includes>
- </resource>
- </resources>
- </build>
- public class Users {
- private Integer userId;
- private String userName;
- private String userPass;
-
- public Users() {
- }
-
- public Users(Integer userId, String userName, String userPass) {
- this.userId = userId;
- this.userName = userName;
- this.userPass = userPass;
- }
-
- public Integer getUserId() {
- return userId;
- }
-
- public void setUserId(Integer userId) {
- this.userId = userId;
- }
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public String getUserPass() {
- return userPass;
- }
-
- public void setUserPass(String userPass) {
- this.userPass = userPass;
- }
-
- @Override
- public String toString() {
- return "Users{" +
- "userId=" + userId +
- ", userName='" + userName + '\'' +
- ", userPass='" + userPass + '\'' +
- '}';
- }
- }
- public class Accounts {
- private Integer aId;
- private String aName;
- private String aContact;
-
- public Accounts() {
- }
-
- public Accounts(Integer aId, String aName, String aContact) {
- this.aId = aId;
- this.aName = aName;
- this.aContact = aContact;
- }
-
- public Integer getaId() {
- return aId;
- }
-
- public void setaId(Integer aId) {
- this.aId = aId;
- }
-
- public String getaName() {
- return aName;
- }
-
- public void setaName(String aName) {
- this.aName = aName;
- }
-
- public String getaContact() {
- return aContact;
- }
-
- public void setaContact(String aContact) {
- this.aContact = aContact;
- }
-
- @Override
- public String toString() {
- return "Accounts{" +
- "aId=" + aId +
- ", aName='" + aName + '\'' +
- ", aContact='" + aContact + '\'' +
- '}';
- }
- }
- public interface UsersMapper {
- //新增用户
- int addUsers(Users users);
- }
- public interface AccountsMapper {
- //新增账户
- int addAccounts(Accounts accounts);
- }
注意:针对整合Spring+Mybatis框架而言,每个Mapper业务接口都得有数据来支撑,否则就是一个空壳,数据支持来自于每个与Mapper业务接口相对应(指的是文件名相同,后缀不同.java/.xml)的XML文件,此XML文件是Mybatis映射SQL数据到Mapper层的。
严格按照规范和要求,此XML文件必须与Mapper接口同在mapper根目录下,如下图所示:

- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.dhrj.java.zsitking.mapper.UsersMapper">
- <!--
- int addUsers(Users users);
- 实体类
- private Integer userId;
- private String userName;
- private String userPass;
- -->
- <insert id="addUsers" parameterType="users">
- insert into users values(#{userId},#{userName},#{userPass})
- </insert>
- </mapper>
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.dhrj.java.zsitking.mapper.AccountsMapper">
- <!--
- int addAccounts(Accounts accounts);
- 实体类
- private Integer aId;
- private String aName;
- private String aContact;
- -->
- <insert id="addAccounts" parameterType="accounts">
- insert into accounts values(#{aId},#{aName},#{aContact})
- </insert>
- </mapper>
老规矩:有业务先上接口,逐步搭建MVC架构。
- public interface UsersService {
- //新增用户
- int addUsers(Users users);
- }
- public interface AccountsService {
- //新增账户
- int addAccounts(Accounts accounts);
- }
重要前提条件————>业务逻辑层必须标注@Service交给Spring去创建对象,如A、B同理,将对象注入到IOC容器中,提供给控制层Controller使用。
说明:《在所有的业务逻辑层中一定会有数据访问层的对象》
A:Mybatis容器原生方式获取数据访问层的对象(不推荐,此方式比较low,代码没有
复用,开发效率低。)
1、读取核心配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
2、创建工厂对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
3、取出sqlSession
sqlSession = factory.openSession(true);//自动提交事务
4、取出动态代理的对象,完成接口中方法的调用,实则是调用xml文件中标签的功能
uMapper = sqlSession.getMapper(UsersMapper.class);
B:Spring框架IOC控制反转方式获取数据访问层的对象(推荐,此方式比较高,代码
复用,开发效率高。)
1、利用Spring注解的方式,将数据访问层对象注入(创建单例对象)到Spring的
Beans工厂中
2、此时Spring框架在内存中创建了一个UsersMapper接口实现类型对象,并且将其存储到了IOC容器中,这个对象就是我们所需要的对象
3、使用@Autowired按类型将UsersMapper接口实现类型对象注入到业务逻辑层的对象中-若在此条件下单例模式是默认的(scope="singleton"),使用
@Autowired或@Resources自动查找引用数据访问层的对象都行-如果是多例
模式(scope="prototype"),则需要使用@Autowired+@Qualifier或
@Resources自动查找数据访问层的对象
4、这样业务逻辑层就可以通过接口实现类型对象直接调用数据访问层的业务方法
C:以上A和B的区别:
1、共同点:都是使用JDK动态代理,CGLib代理需另配置细节参数(根据目标对象没有实现接口,采用子类CGLib代理即可)。
2、不同点:方式一:使用IO流+控制正转创建SqlSession对象,方式二:使用基于注解的Spring控制反转。
- @Service //交给Spring去创建对象
- public class UsersServiceImpl implements UsersService {
-
- //Spring按类型自动注入usersMapper实现类的实例
- @Autowired
- private UsersMapper usersMapper;
-
- @Override
- public int addUsers(Users users) {
- return usersMapper.addUsers(users);
- }
- }
- @Service //交给Spring去创建对象
- public class AccountsServiceImpl implements AccountsService {
-
- //在所有的业务逻辑层中一定会有数据访问层的对象
- @Autowired
- private AccountsMapper accountsMapper;
-
- @Override
- public int addAccounts(Accounts accounts) {
- return accountsMapper.addAccounts(accounts);
- }
- }
说明:value值根据本机设备更改即可。
- jdbc.driverClassName=com.mysql.cj.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/sm?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
- jdbc.username=root
- jdbc.password=root
说明:将JDBC已经配置到连接协议、URL、用户名、密码以注入bean方式交给Spring管理。
- <?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:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
-
- <!-- 读取JDBC属性配置文件 -->
- <context:property-placeholder location="jdbc.properties"/>
- <!-- 创建数据源 -->
- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
- <property name="driverClassName" value="${jdbc.driverClassName}"/>
- <property name="url" value="${jdbc.url}"/>
- <property name="username" value="${jdbc.username}"/>
- <property name="password" value="${jdbc.password}"/>
- </bean>
- <!--配置SqlSessionFactoryBean类-->
- <bean class="org.mybatis.spring.SqlSessionFactoryBean">
- <!--配置数据源-->
- <property name="dataSource" ref="dataSource"/>
- <!--配置MyBatis的核心配置文件-->
- <property name="configLocation" value="SqlMapConfig.xml"/>
- <!--注册实体类的别名-->
- <property name="typeAliasesPackage" value="com.dhrj.java.zsitking.entity"/>
- </bean>
- <!--注册mapper.xml文件-->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.dhrj.java.zsitking.mapper"/>
- </bean>
- </beans>
说明:因为是基于注解开发,在业务逻辑层(Mapper接口实现类)中使用了@Service,所以需要在Spring配置文件中,添加包扫描,才能调取全限定名称通过Java反射机制创建实例对象。此外,可以单个包的方式导入mapper配置文件。
- <?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:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
-
- <!--导入applicationContext_mapper.xml文件-->
- <import resource="applicationContext_mapper.xml"/>
- <!-- SM是基于注解的开发,所以添加包扫描 -->
- <context:component-scan base-package="com.dhrj.java.zsitking.service.impl"/>
- <!-- 事务处理 -->
-
- </beans>
说明:按理说,Spirng整合MyBatis,全部参数(数据源+事务提交状态+SQL+入参+出参+连接池等信息)都应当配置在Spring配置文件中,交给Spring容器以注入Bean方式自动创建对象和管理使用,SqlMapConfig.xml文件存在意义——>能够配置Mybatis特有属性,Spring配置无法实现,如开启日志等情况。
- <?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>
- <!-- 数据源+事务提交状态+SQL+入参+出参+连接池等信息交给Spring以注入Bean的方式创建对象和管理使用 -->
- <!-- 设置日志在控制台输出 -->
- <settings>
- <setting name="logImpl" value="STDOUT_LOGGING"/>
- </settings>
-
- </configuration>
- public class TestSM {
-
- private ApplicationContext ac;
-
- @Before
- public void before() {
- //1.创建容器并启动
- ac = new ClassPathXmlApplicationContext("applicationContext_service.xml");
- }
- @Test
- public void testUsers() {
- //2.取出UsersServiceImpl
- UsersService uService = (UsersService) ac.getBean("usersServiceImpl");
- int num = uService.addUsers(new Users(1998,"张松","root"));
- System.out.println(num);
- }
-
- @Test
- public void testAccounts() {
- //2.取出UsersServiceImpl
- AccountsService accountsService = (AccountsService) ac.getBean("accountsServiceImpl");
- int num = accountsService.addAccounts(new Accounts(1,"张松的账户","账户余额"));
- System.out.println(num);
- }
- }




重点须知:程序测试结果正常,均新增了数据。 这里需要知道,为什么控制会打印SQL会话连接、数据源、JDBC对象内存地址、所执行SQL、参数(对象参数转为SQL参数)、到最终关闭会话连接,释放内存资源这一系列过程???回想一下?我们是不是已经在SqlMapConfig.xml中配置日志打印呢?那如果将日志打印功能设置关闭(注释掉)还会打印吗???

结论:关闭不再打印SQL处理过程的等信息,即是验证了Spring容器整合MyBatis,并没有将MyBatis独有的日志打印功能进行整合实现,又验证了SqlMapConfig.xml配置文件存在是有意义的。
仅自己学习记录,如有错误,敬请谅解~,谢谢~~~