Spring 集成 MyBatis

1.将 MyBatis 与 Spring 进行整合,主要解决的问题就是将 SqlSessionFactory 对象交由 Spring 来管理

2.整合只需要将 SqlSessionFactory 的对象生成器 SqlSessionFactoryBean 注册在 Spring 容器中,再将其注入给 Dao 的实现类即可完成整合。

3.实现 Spring 与 MyBatis 的整合。常用的方式:扫描的 Mapper 动态代理。

SM整合的步骤(示例)

1.建表(在数据库中添加新表)

use ssm;

create table users(
  userid int primary key,
  uname varchar(20),
  upass varchar(20)
);

create table accounts(
 aid  int primary key,
 aname varchar(20),
 acontent varchar(50)
);

2.新建项目,选择quickstart模板
3.修改完善目录
4.修改pom.xml文件,添加相关的依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.dy</groupId>
  <artifactId>spring-sm</artifactId>
  <version>1.0</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <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-aspects</artifactId>
    <version>5.3.19</version>
  </dependency>

  <!--spring核心ioc-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.19</version>
  </dependency>

  <!--做spring事务用到的-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.19</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.19</version>
  </dependency>

  <!--mybatis依赖-->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</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.9</version>
  </dependency>
  </dependencies>

  <build>
    <!--目的是把src/main/java目录中的xml文件包含到输出结果中。输出到classes目录中-->
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
      </resource>
    </resources>
  </build>
</project>

5.添加SqlMapConfig.xml文件

<?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语名-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>

6.添加jdbc.propertiest属性文件到resources目录下

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp&characterEncoding=gbk
jdbc.username=root
jdbc.password=123456

7.添加applicationContext_mapper.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: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.properties-->
    <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.dy.pojo"/>
    </bean>
    <!--注册mapper.xml文件-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.dy.mapper"/>
    </bean>
</beans>

8.添加applicationContext_service.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:context="http://www.springframework.org/schema/context" 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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--导入applicationContext_mapper.xml文件-->
    <import resource="applicationContext_mapper.xml"/>
    <!--SM是基于注解的开发,所以添加包扫描-->
    <context:component-scan base-package="com.dy.service.impl"/>
    <!--事务处理-->

</beans>

9.在com.dy.pojo包下添加Users实体类

package com.dy.pojo;

public class Users {
    private Integer userid;
    private String uname;
    private String upass;

    @Override
    public String toString() { return "Users{" +"userid=" + userid + ", uname='" + uname + '\'' + ", upass='" + upass + '\'' + '}'; }

    public Integer getUserid() { return userid; }
    public void setUserid(Integer userid) { this.userid = userid; }

    public String getUname() {  return uname;}
    public void setUname(String uname) {this.uname = uname;}

    public String getUpass() { return upass;}
    public void setUpass(String upass) { this.upass = upass; }

    public Users(Integer userid, String uname, String upass) {this.userid = userid; this.uname = uname;this.upass = upass; }

    public Users() { }
}

10.在com.dy.mapper包下添加UsersMapper接口和UsersMapper.xml文件

public interface UsersMapper {
    int insert(Users users);//添加用户
}
<?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.dy.mapper.UsersMapper">
    <insert id="insert" parameterType="users">
        insert into users values(#{userid},#{uname},#{upass})
    </insert>
</mapper>

11.在com.dy.service包下,添加UsersService接口

public interface UsersService {
   int insert (Users users); //添加用户
}

  在com.dy.service.mipl包下UsersServiceImpl实现类 

@Service  //交给Spring去创建对象
public class UsersServiceImpl implements UsersService {
    //切记切记:在所有的业务逻辑层中一定会有数据访问层的对象
    @Autowired  //直接按类型自动注入
    // 在usersMapper.xml中完成功能的动态代理对象已经注册到到applicationContext_mapper.xml 当中
    UsersMapper usersMapper;
    @Override
    public int insert(Users users) {
        return usersMapper.insert(users);
    }
}

12.添加测试类进行功能测试

public class MyTest {
  @Test
  public void testUsers() {
    //创建容器并启动
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_service.xml");
    //取出UsersServiceImpl
    UsersService uService = (UsersService) ac.getBean("usersServiceImpl");
    int num = uService.insert(new Users(100,"张三","123"));
    System.out.println(num);
    }
}
测试结果:
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ddea849] was not registered for synchronization because synchronization is not active
5月 16, 2022 6:22:13 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {dataSource-1} inited
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5d465e4b] will not be managed by Spring
==>  Preparing: insert into users values(?,?,?)
==> Parameters: 100(Integer), 张三(String), 123(String)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ddea849]
1

创建账户实体类

1.在com.dy.pojo包下添加Accounts实体类

package com.dy.pojo;

public class Accounts {
    private Integer aid;
    private String aname;
    private String acontent;
    @Override
    public String toString() { return "Accounts{" +"aid=" + aid + ", aname='" + aname + '\'' + ", acontent='" + acontent + '\'' + '}'; }

    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 getAcontent() { return acontent; }
    public void setAcontent(String acontent) {this.acontent = acontent;}

    public Accounts(Integer aid, String aname, String acontent) {this.aid = aid; this.aname = aname; this.acontent = acontent; }

    public Accounts() {}
}

2.在com.dy.mapper包下添加AccountsMapper接口和AccountsMapper.xml文件 

public interface AccountsMapper {
  int save(Accounts accounts);   //增加帐户
}
<?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.dy.mapper.AccountsMapper">
    <insert id="save" parameterType="accounts">
        insert into accounts values(#{aid},#{aname},#{acontent})
    </insert>
</mapper>

 3.在com.dy.service包下,添加AccountsService接口

public interface AccountsService {
    int save(Accounts accounts);
}

  在com.dy.service.mipl包下AccountsServiceImpl实现类 

@Service
public class AccountsServiceImpl implements AccountsService {
    //一定会有数据访问层的对象
    @Autowired
    AccountsMapper accountsMapper;
    @Override
    public int save(Accounts accounts) {
        int num = 0;
        num = accountsMapper.save(accounts);
        System.out.println("增加帐户成功!num="+num);
        return num;
    }
}

 4.测试类

@Test
public void testAccounts(){
  //创建容器并启动
  ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_service.xml");
  AccountsService accountsService = (AccountsService) ac.getBean("accountsServiceImpl");
  System.out.println(accountsService.getClass());
  accountsService.save(new Accounts(206,"李四6","帐户安全6666!"));
    }
测试结果:
增加帐户成功!num=1

Spring的两种事务处理方式

1.注解式的事务
使用@Transactional注解完成事务控制,此注解可添加到类上,则对类中所有方法执行事务的设定.此注解可添加到方法上,只是对此方法执行事务的处理.

1.在applicationContext_service.xml中添加事物管理器

<!--1.添加事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--因为事务必须关联数据库处理,所以要配置数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2.添加事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>

2.在AccountsServiceImpl实现类中手动添加一个异常(测试事务的回滚处理)

@Service
@Transactional(propagation = Propagation.REQUIRED)//使用声明式事务方法需要去掉该注解
public class AccountsServiceImpl implements AccountsService {
    //一定会有数据访问层的对象
    @Autowired
    AccountsMapper accountsMapper;
    @Override
    public int save(Accounts accounts) {
        int num = 0;
        num = accountsMapper.save(accounts);
        System.out.println("增加帐户成功!num="+num);
        System.out.println(1/0);//手工抛出异常 ArithmeticException算数异常
        return num;
    }
}

当方法在执行过程中,发生任何的错误,@Transactional事务注解能保证将已插入成功的操作撤销掉

 3.在UsersServiceImpl实现类中调用(包含)AccountsServiceImpl的功能

@Service  //交给Spring去创建对象
@Transactional(propagation = Propagation.REQUIRED) //使用声明式事务方法需要去掉该注解
public class UsersServiceImpl implements UsersService {
    @Autowired
    UsersMapper usersMapper;
    @Autowired
    AccountsService accountsService;
    @Override
    public int insert(Users users) {
        int num = usersMapper.insert(users);
        System.out.println("用户增加成功!num="+num);
        //调用帐户的增加操作,调用的帐户的业务逻辑层的功能
        num = accountsService.save(new Accounts(300,"王五","帐户好的呢!"));
        return num;
    }
}

Spring事务的传播特性:多个事务之间的合并,互斥等都可以通过设置事务的传播特性来解决

常用:

PROPAGATION_REQUIRED:必被包含事务(增删改必用)
PROPAGATION_REQUIRES_NEW:自己新开事务,不管之前是否有事务
PROPAGATION_SUPPORTS:支持事务,如果加入的方法有事务,则支持事务,如果没有,不单开事务
PROPAGATION_NEVER:不能运行中事务中,如果包在事务中,抛异常
PROPAGATION_NOT_SUPPORTED:不支持事务,运行在非事务的环境

以下是在不同状态事务下的测试结果:(项目中的所有事务,必须添加到业务逻辑层上)

@Transactional(propagation = Propagation.*******)

2.声明式事务(必须掌握)

在配置文件中添加一次,整个项目遵循事务的设定

要求项目中的方法命名有规范:配置事务切面时可以使用通配符*来匹配所有方法
1.完成增加操作包含    add  save  insert  set
2.更新操作包含   update   change  modify  
3.删除操作包含   delete   drop    remove  clear
4.查询操作包含   select   find    search  get 

创建新的配置文件applicationContext_trans.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: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 https://www.springframework.org/schema/context/spring-context.xsd  http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--此配置文件与applicationContext_service.xml的功能一样,只是事务配置不同-->
    <!--导入applicationContext_mapper.xml-->
    <import resource="applicationContext_mapper.xml"/>
    <!--添加包扫描-->
    <context:component-scan base-package="com.dy.service.impl"/>
    <!--添加事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置事务切面-->
    <tx:advice id="myadvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*select*" read-only="true"/>
            <tx:method name="*find*" read-only="true"/>
            <tx:method name="*search*" read-only="true"/>
            <tx:method name="*get*" read-only="true"/>
            <tx:method name="*insert*" propagation="REQUIRED"/>
            <!--可指定异常类型,不处理,不进行回滚-->
            <!--<tx:method name="*insert*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>  指定算数异常不回滚-->
            <tx:method name="*add*" propagation="REQUIRED"/>
            <tx:method name="*save*" propagation="REQUIRED"/>
            <tx:method name="*set*" propagation="REQUIRED"/>
            <tx:method name="*update*" propagation="REQUIRED"/>
            <tx:method name="*change*" propagation="REQUIRED"/>
            <tx:method name="*modify*" propagation="REQUIRED"/>
            <tx:method name="*delete*" propagation="REQUIRED"/>
            <tx:method name="*remove*" propagation="REQUIRED"/>
            <tx:method name="*drop*" propagation="REQUIRED"/>
            <tx:method name="*clear*" propagation="REQUIRED"/>
            <tx:method name="*" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>
    <!--绑定切面和切入点-->
    <aop:config>
        <aop:pointcut id="mycut" expression="execution(* com.dy.service.impl.*.*(..))"/>
        <aop:advisor advice-ref="myadvice" pointcut-ref="mycut"/>
    </aop:config>
</beans>

测试类 

 @Test
public void testTrans(){
  //创建容器并启动
  ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_trans.xml");
  //取出UsersServiceImpl
  UsersService uService = (UsersService) ac.getBean("usersServiceImpl");
  int num = uService.insert(new Users(100,"张三","123"));
  System.out.println(num);
    }

拓展知识(@Transactional注解参数详解)

@Transactional(括号中的内容说明)

propagation = Propagation.REQUIRED 事务的传播特性

noRollbackForClassName = "异常名称" 指定哪些异常不回滚,使用的是异常的名称 

noRollbackFor = 异常名称.class 指定发生什么异常不回滚,使用的是异常的类型

rollbackForClassName = "异常名称" 指定发生什么异常必须回滚

rollbackFor = 异常名称.class 指定发生什么异常必须回滚,使用的是异常的类型

timeout = -1 连接超时设置,默认值是-1,表示永不超时

readOnly = false 默认是false增删改操作,如果是查询操作,必须设置为true

isolation = Isolation.DEFAULT 使用数据库自已的隔离级别

Spring中事务的五大隔离级别(了解)
1.未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
2.提交读(Read Committed):只能读取到已经提交的数据。多数数据库默认都是该级别 (不重复读)
3.可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读,但是innoDB解决了幻读
4.串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
5.使用数据库默认的隔离级别isolation = Isolation.DEFAULT
MySQL:mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读
Oracle:oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。默认系统事务隔离级别是READ COMMITTED,也就是读已提交

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌路学java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值