栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring整合Mybatis(手把手教程,有头就能学会)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring整合Mybatis(手把手教程,有头就能学会)

目录

必读:学习建议

一、Spring整合MyBatis步骤

第一步 引入依赖包

第二步 编写实体类、三层模式

实体类 SysUser.java

数据库DAO接口 SysUserMapper.java

MyBatis映射文件 SysUserMapper.xml

数据库接口实现类 SysUserMapperImpl.java

服务层接口 SysUserService.java

服务层接口实现类 SysUserServiceImpl.java

第三步 配置MyBatis核心配置文件

mybatis-config.xml

第四步 配置Spring核心配置文件

applicationContext.xml

单元测试

在项目test下创建 SysUserTest.java

优化一 使用SqlSessionDaoSupport替换SqlSessionTemplate

在 com.bdqn.dao 包下新建 SysUserMapperDaoSupportImpl.java

修改 applicationContext.xml 对应配置

优化二 使用MapperFactoryBean注入映射器

修改 applicationContext.xml 对应配置

优化三 使用MapperScannerConfig注入映射器

修改 applicationContext.xml 对应配置

完整 applicationContext.xml 配置

 注解方式  使用注解简化业务层配置

使用注解修改 SysUserServiceImpl.java 文件

总结:

修改 applicationContext.xml 配置

每次优化配置后,重新运行单元测试

Spring整合MyBatis配置总结

 二、配置声明式事务

Spring中如何配置声明式事务?

准备工作

SysUserMapper.java 接口增加 add(SysUser sysUser) 方法

SysUserService.java 接口增加 add(SysUser sysUser) 方法

SysUserServiceImpl.java 实现类增加 add(SysUser sysUser) 方法

SysUserTest.java 测试类中增加 testAddUser 方法

方式一:编写配置的方式进行事务配置

第一步 导入命名空间

第二步 定义事务管理器

第三步 设置事务属性

第四步 定义事务切面

方式二:使用注解进行事务配置

applicationContext.xml使用注解进行事务配置

SysUserServiceImpl.java

测试事务


必读:学习建议

本教程手把手教学,介绍如何通过Spring框架整合MyBatis。跟着教程步骤可以完成MyBatis与Spring框架的整合。赶快试试吧!配置过程一定要细心一点~~

知识扩展:

各种数据库连接池对比:https://blog.csdn.net/wawa3338/article/details/81380662

一、Spring整合MyBatis步骤

第一步 引入依赖包
项目所依赖的jar包如下:
Maven: aopalliance:aopalliance:1.0 
Maven: com.google.protobuf:protobuf-java:3.6.1 
Maven: commons-dbcp:commons-dbcp:1.4 
Maven: commons-pool:commons-pool:1.6 
Maven: junit:junit:4.13 
Maven: log4j:log4j:1.2.17 
Maven: mysql:mysql-connector-java:8.0.18 
Maven: org.aspectj:aspectjweaver:1.9.6 
Maven: org.hamcrest:hamcrest:2.2 
Maven: org.hamcrest:hamcrest-core:2.2 
Maven: org.mybatis:mybatis:3.5.6 
Maven: org.mybatis:mybatis-spring:2.0.6 
Maven: org.springframework:spring-aop:5.3.4 
Maven: org.springframework:spring-beans:5.3.4 
Maven: org.springframework:spring-context:5.3.4 
Maven: org.springframework:spring-core:5.3.4 
Maven: org.springframework:spring-expression:5.3.4 
Maven: org.springframework:spring-jcl:5.3.4 
Maven: org.springframework:spring-jdbc:5.3.4 
Maven: org.springframework:spring-tx:5.3.4 

注意:使用Maven创建项目,需要用到的所有依赖包如上。其中Maven: org.mybatis:mybatis-spring:2.0.6是MyBatis使用Spring框架整合的依赖包。

pom.xml




  4.0.0

  com.bdqn
  s3-spring-mybatis
  1.0-SNAPSHOT

  s3-spring-mybatis

  
    UTF-8
    1.8
    1.8
  

  
    
      junit
      junit
      4.13
      test
    
    
      org.springframework
      spring-aop
      5.3.4
    
    
      org.springframework
      spring-beans
      5.3.4
    
    
      org.springframework
      spring-context
      5.3.4
    
    
      org.springframework
      spring-core
      5.3.4
    
    
      org.springframework
      spring-expression
      5.3.4
    
    
      aopalliance
      aopalliance
      1.0
    
    
      org.aspectj
      aspectjweaver
      1.9.6
    
    
      org.hamcrest
      hamcrest-core
      2.2
      test
    
    
      log4j
      log4j
      1.2.17
    
    
      org.mybatis
      mybatis
      3.5.6
    
    
      mysql
      mysql-connector-java
      8.0.18
    
    
    
      org.mybatis
      mybatis-spring
      2.0.6
    
    
      org.springframework
      spring-jdbc
      5.3.4
    
    
      org.springframework
      spring-tx
      5.3.4
    
    
      commons-dbcp
      commons-dbcp
      1.4
    
    
      commons-pool
      commons-pool
      1.6
    
  

  
  
    
      
        src/main/java
        
          ***.xml
        
      
      
        src/main/resources
        
            ***.xml
        
       
    
  

第二步 编写实体类、三层模式

实体类 SysUser.java
package com.onc.pojo;

import java.util.Date;


public class SysUser {

   private Integer id; //id
   private String account; //用户编码
   private String realName; //用户名称
   private String password; //用户密码
   private Integer sex;  //性别
   private Date birthday;  //出生日期
   private String phone;   //电话
   private String address; //地址
   private Integer roleId;    //用户角色ID
   private Integer createdUserId;   //创建者
   private Date createdTime; //创建时间
   private Integer updatedUserId;     //更新者
   private Date updatedTime;   //更新时间

   private Integer age;//年龄
   private String roleIdName; //用户角色名称

   public Integer getAge() {
      
      Date date = new Date();
      Integer age = date.getYear() - birthday.getYear();
      return age;
   }

   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   public String getAccount() {
      return account;
   }

   public void setAccount(String account) {
      this.account = account;
   }

   public String getRealName() {
      return realName;
   }

   public void setRealName(String realName) {
      this.realName = realName;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public Integer getSex() {
      return sex;
   }

   public void setSex(Integer sex) {
      this.sex = sex;
   }

   public Date getBirthday() {
      return birthday;
   }

   public void setBirthday(Date birthday) {
      this.birthday = birthday;
   }

   public String getPhone() {
      return phone;
   }

   public void setPhone(String phone) {
      this.phone = phone;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }

   public Integer getRoleId() {
      return roleId;
   }

   public void setRoleId(Integer roleId) {
      this.roleId = roleId;
   }

   public Integer getCreatedUserId() {
      return createdUserId;
   }

   public void setCreatedUserId(Integer createdUserId) {
      this.createdUserId = createdUserId;
   }

   public Date getCreatedTime() {
      return createdTime;
   }

   public void setCreatedTime(Date createdTime) {
      this.createdTime = createdTime;
   }

   public Integer getUpdatedUserId() {
      return updatedUserId;
   }

   public void setUpdatedUserId(Integer updatedUserId) {
      this.updatedUserId = updatedUserId;
   }

   public Date getUpdatedTime() {
      return updatedTime;
   }

   public void setUpdatedTime(Date updatedTime) {
      this.updatedTime = updatedTime;
   }

   public void setAge(Integer age) {
      this.age = age;
   }

   public String getRoleIdName() {
      return roleIdName;
   }

   public void setRoleIdName(String roleIdName) {
      this.roleIdName = roleIdName;
   }

   @Override
   public String toString() {
      return "SysUser{" +
            "id=" + id +
            ", account='" + account + ''' +
            ", realName='" + realName + ''' +
            ", password='" + password + ''' +
            ", sex=" + sex +
            ", birthday=" + birthday +
            ", phone='" + phone + ''' +
            ", address='" + address + ''' +
            ", roleId=" + roleId +
            ", createdUserId=" + createdUserId +
            ", createdTime=" + createdTime +
            ", updatedUserId=" + updatedUserId +
            ", updatedTime=" + updatedTime +
            ", age=" + age +
            ", roleIdName='" + roleIdName + ''' +
            '}';
   }
}

数据库DAO接口 SysUserMapper.java
package com.onc.dao;

import com.onc.pojo.SysUser;

import java.util.List;


public interface SysUserMapper {

    
    public List selectSysUserList(SysUser sysUser);
}

MyBatis映射文件 SysUserMapper.xml




    
    
        
    

    
    

数据库接口实现类 SysUserMapperImpl.java
package com.onc.dao;

import com.onc.pojo.SysUser;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;


public class SysUserMapperImpl implements SysUserMapper {

    // mybatis-spring包中提供的实现了SqlSession接口的类,用来操作数据库
    private SqlSessionTemplate sqlSession;

    
    @Override
    public List selectSysUserList(SysUser sysUser) {
        return sqlSession.getMapper(SysUserMapper.class).selectSysUserList(sysUser);
    }

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
}

服务层接口 SysUserService.java
package com.onc.service;


import com.onc.pojo.SysUser;

import java.util.List;


public interface SysUserService {

    
    public List getList(SysUser sysUser);
}

服务层接口实现类 SysUserServiceImpl.java
package com.onc.service;

import com.onc.dao.SysUserMapper;
import com.onc.pojo.SysUser;

import java.util.List;


public class SysUserServiceImpl implements SysUserService {

    private SysUserMapper sysUserMapper;

    @Override
    public List getList(SysUser sysUser) {
        try {
            return sysUserMapper.selectSysUserList(sysUser);
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw e;
        }
    }

    public void setSysUserMapper(SysUserMapper sysUserMapper) {
        this.sysUserMapper = sysUserMapper;
    }

}

第三步 配置MyBatis核心配置文件

mybatis-config.xml




    
    
        
    

注意:将数据源的配置交给Spring完成,按如上配置,注释掉引入外部数据源配置和MyBatis数据源环境配置。

第四步 配置Spring核心配置文件

applicationContext.xml



    
    
        
        
        
        
    

    
    
        
        
        
        
        
        
            
                classpath:com/onc/dao*.xml
            
        
    

    
    
        
        
    
    
    
        
    
    
    
        
    

单元测试

在项目test下创建 SysUserTest.java
package com.onc;

import com.onc.pojo.SysUser;
import com.onc.service.SysUserService;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;


public class SysUserTest {

    private Logger logger = Logger.getLogger(SysUserTest.class);

    @Before
    public void setUp() throws Exception {
    }

    @Test
    public void testGetUserList() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SysUserService userService = (SysUserService) ctx.getBean("sysUserService");
        List userList = new ArrayList();
        SysUser sysUser = new SysUser();
        sysUser.setRealName("赵");
        sysUser.setRoleId(2);
        userList = userService.getList(sysUser);

        for (SysUser userResult : userList) {
            logger.debug("testGetUserList account: "
                    + userResult.getAccount() + " and realName: "
                    + userResult.getRealName() + " and roleId: "
                    + userResult.getRoleId() + " and roleName: "
                    + userResult.getRoleIdName() + " and address: "
                    + userResult.getAddress());
        }
    }

}

测试结果

C:Javajdk1.8.0_261binjava.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3libidea_rt.jar=58319:C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3libidea_rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3pluginsjunitlibjunit5-rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3pluginsjunitlibjunit-rt.jar;C:Javajdk1.8.0_261jrelibcharsets.jar;C:Javajdk1.8.0_261jrelibdeploy.jar;C:Javajdk1.8.0_261jrelibextaccess-bridge-64.jar;C:Javajdk1.8.0_261jrelibextcldrdata.jar;C:Javajdk1.8.0_261jrelibextdnsns.jar;C:Javajdk1.8.0_261jrelibextjaccess.jar;C:Javajdk1.8.0_261jrelibextjfxrt.jar;C:Javajdk1.8.0_261jrelibextlocaledata.jar;C:Javajdk1.8.0_261jrelibextnashorn.jar;C:Javajdk1.8.0_261jrelibextsunec.jar;C:Javajdk1.8.0_261jrelibextsunjce_provider.jar;C:Javajdk1.8.0_261jrelibextsunmscapi.jar;C:Javajdk1.8.0_261jrelibextsunpkcs11.jar;C:Javajdk1.8.0_261jrelibextzipfs.jar;C:Javajdk1.8.0_261jrelibjavaws.jar;C:Javajdk1.8.0_261jrelibjce.jar;C:Javajdk1.8.0_261jrelibjfr.jar;C:Javajdk1.8.0_261jrelibjfxswt.jar;C:Javajdk1.8.0_261jrelibjsse.jar;C:Javajdk1.8.0_261jrelibmanagement-agent.jar;C:Javajdk1.8.0_261jrelibplugin.jar;C:Javajdk1.8.0_261jrelibresources.jar;C:Javajdk1.8.0_261jrelibrt.jar;D:Worksktjiaoyus3-spring-mybatistargettest-classes;D:Worksktjiaoyus3-spring-mybatistargetclasses;D:Sourcemavenrepositoryjunitjunit4.13junit-4.13.jar;D:Sourcemavenrepositoryorgspringframeworkspring-aop5.3.4spring-aop-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-beans5.3.4spring-beans-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-context5.3.4spring-context-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-core5.3.4spring-core-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-jcl5.3.4spring-jcl-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-expression5.3.4spring-expression-5.3.4.jar;D:Sourcemavenrepositoryaopallianceaopalliance1.0aopalliance-1.0.jar;D:Sourcemavenrepositoryorgaspectjaspectjweaver1.9.6aspectjweaver-1.9.6.jar;D:Sourcemavenrepositoryorghamcresthamcrest-core2.2hamcrest-core-2.2.jar;D:Sourcemavenrepositoryorghamcresthamcrest2.2hamcrest-2.2.jar;D:Sourcemavenrepositorylog4jlog4j1.2.17log4j-1.2.17.jar;D:Sourcemavenrepositoryorgmybatismybatis3.5.6mybatis-3.5.6.jar;D:Sourcemavenrepositorymysqlmysql-connector-java8.0.18mysql-connector-java-8.0.18.jar;D:Sourcemavenrepositorycomgoogleprotobufprotobuf-java3.6.1protobuf-java-3.6.1.jar;D:Sourcemavenrepositoryorgmybatismybatis-spring2.0.6mybatis-spring-2.0.6.jar;D:Sourcemavenrepositoryorgspringframeworkspring-jdbc5.3.4spring-jdbc-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-tx5.3.4spring-tx-5.3.4.jar;D:Sourcemavenrepositorycommons-dbcpcommons-dbcp1.4commons-dbcp-1.4.jar;D:Sourcemavenrepositorycommons-poolcommons-pool1.6commons-pool-1.6.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.bdqn.SysUserTest,testGetUserList 
[DEBUG] 2021-05-17 01:14:18,457 com.bdqn.SysUserTest - testGetUserList account: zhaogang and realName: 赵刚 and roleId: 2 and roleName: 店长 and address: 北京市丰台区管庄新月小区 
 
Process finished with exit code 0 

 至此,Spring整合MyBatis配置完成。

优化一 使用SqlSessionDaoSupport替换SqlSessionTemplate

除了直接使用SqlSessionTempIate获取SqlSession实例处理数据的方式外,MyBatis-Spring还提供了SqlSessionDaoSupport类来简化SqlSessionTemplate。通过 this.getSqlSession() 获取到 SqlSession 对象来执行数据库操作。

在 com.bdqn.dao 包下新建 SysUserMapperDaoSupportImpl.java
package com.onc.dao;

import com.onc.pojo.SysUser;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;


public class SysUserMapperDaoSupportImpl extends SqlSessionDaoSupport implements SysUserMapper {

    
    @Override
    public List selectSysUserList(SysUser sysUser) {
        return this.getSqlSession().getMapper(SysUserMapper.class).selectSysUserList(sysUser);
    }

}

注意:继承了SqlSessionDaoSupport之后,不需要定义属性SqlSession sqlSession直接通过this.getSqlSession()获取到 SqlSession 对象来执行数据库操作。

修改 applicationContext.xml 对应配置





    

注意:注释第一种方式SqlSessionTemplate版本,替换为第二种方式,使用SqlSessionDaoSupport版本。

优化二 使用MapperFactoryBean注入映射器

MyBatis-Spring提供的MapperFactoryBean能够以配置的方式生成映射器的实现类,并注入给业务组件,无需编写DAO实现类。

修改 applicationContext.xml 对应配置

    
    
    
    
    
    
    











    
    

 注意:通过使用MapperFactoryBean方式(第三种)配置后,无需编写DAO的实现类,只需编写Mapper.xml的映射文件。

优化三 使用MapperScannerConfig注入映射器

使用MapperFactoryBean对映射器做配置,在很大程度上简化了DAO模块的编码。不过,如果映射器很多,则相应的配置项也会很多。为了简化配置工作量,MyBatis-Spring中提供了MapperScannerConfigurer,它可以扫描指定包中的接口并将它们直接注册为MapperFactoryBean。

修改 applicationContext.xml 对应配置











    

注意:通过使用MapperScannerConfigurer方式(第四种)配置后,指定的basePackage包称为基准包,MapperScannerConfigurer将递归扫描基准包(包括各层级子包)下所有接口。如果他们在SQL映射文件中定义过,则将它们动态注册为映射器实现类,即可批量生成映射器的实现类了。

完整 applicationContext.xml 配置



    
    
        
        
        
        
    

    
    
        
        
        
        
        
        
        
            
                classpath:com/bdqn/dao*.xml
            
        
    

    
    
        
        
    

    
    
    
    
    
    
    
    
    
    
    
    
        
    
    
    
        
    

 注解方式  使用注解简化业务层配置

映射器被注册到Spring容器时,Spring框架会根据其接口名称为其命名,默认是首字母小写的非完全限定名。例如,SysUserMapper类型的组件默认命名为sysUserMapper。在开发中,可以使用@Autowired或@Resource注解实现对业务组件的依赖注入,以简化业务组件的配置

使用注解修改 SysUserServiceImpl.java 文件
package com.onc.service;

import com.bdqn.dao.SysUserMapper;
import com.bdqn.pojo.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service("sysUserService") // 注册为一个Service层的Bean
public class SysUserServiceImpl implements SysUserService {

    @Autowired // @Resource // 使用注解的方式将DAO层的Bean注入
    private SysUserMapper sysUserMapper;

    @Override
    public List getList(SysUser sysUser) {
        try {
            return sysUserMapper.selectSysUserList(sysUser);
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw e;
        }
    }

}

总结:

Spring注册Bean的注解包括

  1. @Component :用于标注类为一个Bean
  2. @Repository :用于标注DAO类为一个Bean
  3. @Service :用于标注业务类为一个Bean
  4. @Controller :用于标注控制器类为一个Bean

 注意:注解方式配置需要修改Spring配置文件,移除业务层Bean的配置,添加扫描注解定义的业务Bean

修改 applicationContext.xml 配置



    
    
        
        
        
        
    

    
    
        
        
        
        
        
        
        
    

    
    
        
        
    

    
    
    
    
    
    
    
    
    
    
    
    
        
    

    
    
    

    
    

每次优化配置后,重新运行单元测试

测试结果

C:Javajdk1.8.0_261binjava.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3libidea_rt.jar=58319:C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3libidea_rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3pluginsjunitlibjunit5-rt.jar;C:Program FilesJetBrainsIntelliJ IDEA 2020.1.3pluginsjunitlibjunit-rt.jar;C:Javajdk1.8.0_261jrelibcharsets.jar;C:Javajdk1.8.0_261jrelibdeploy.jar;C:Javajdk1.8.0_261jrelibextaccess-bridge-64.jar;C:Javajdk1.8.0_261jrelibextcldrdata.jar;C:Javajdk1.8.0_261jrelibextdnsns.jar;C:Javajdk1.8.0_261jrelibextjaccess.jar;C:Javajdk1.8.0_261jrelibextjfxrt.jar;C:Javajdk1.8.0_261jrelibextlocaledata.jar;C:Javajdk1.8.0_261jrelibextnashorn.jar;C:Javajdk1.8.0_261jrelibextsunec.jar;C:Javajdk1.8.0_261jrelibextsunjce_provider.jar;C:Javajdk1.8.0_261jrelibextsunmscapi.jar;C:Javajdk1.8.0_261jrelibextsunpkcs11.jar;C:Javajdk1.8.0_261jrelibextzipfs.jar;C:Javajdk1.8.0_261jrelibjavaws.jar;C:Javajdk1.8.0_261jrelibjce.jar;C:Javajdk1.8.0_261jrelibjfr.jar;C:Javajdk1.8.0_261jrelibjfxswt.jar;C:Javajdk1.8.0_261jrelibjsse.jar;C:Javajdk1.8.0_261jrelibmanagement-agent.jar;C:Javajdk1.8.0_261jrelibplugin.jar;C:Javajdk1.8.0_261jrelibresources.jar;C:Javajdk1.8.0_261jrelibrt.jar;D:Worksktjiaoyus3-spring-mybatistargettest-classes;D:Worksktjiaoyus3-spring-mybatistargetclasses;D:Sourcemavenrepositoryjunitjunit4.13junit-4.13.jar;D:Sourcemavenrepositoryorgspringframeworkspring-aop5.3.4spring-aop-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-beans5.3.4spring-beans-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-context5.3.4spring-context-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-core5.3.4spring-core-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-jcl5.3.4spring-jcl-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-expression5.3.4spring-expression-5.3.4.jar;D:Sourcemavenrepositoryaopallianceaopalliance1.0aopalliance-1.0.jar;D:Sourcemavenrepositoryorgaspectjaspectjweaver1.9.6aspectjweaver-1.9.6.jar;D:Sourcemavenrepositoryorghamcresthamcrest-core2.2hamcrest-core-2.2.jar;D:Sourcemavenrepositoryorghamcresthamcrest2.2hamcrest-2.2.jar;D:Sourcemavenrepositorylog4jlog4j1.2.17log4j-1.2.17.jar;D:Sourcemavenrepositoryorgmybatismybatis3.5.6mybatis-3.5.6.jar;D:Sourcemavenrepositorymysqlmysql-connector-java8.0.18mysql-connector-java-8.0.18.jar;D:Sourcemavenrepositorycomgoogleprotobufprotobuf-java3.6.1protobuf-java-3.6.1.jar;D:Sourcemavenrepositoryorgmybatismybatis-spring2.0.6mybatis-spring-2.0.6.jar;D:Sourcemavenrepositoryorgspringframeworkspring-jdbc5.3.4spring-jdbc-5.3.4.jar;D:Sourcemavenrepositoryorgspringframeworkspring-tx5.3.4spring-tx-5.3.4.jar;D:Sourcemavenrepositorycommons-dbcpcommons-dbcp1.4commons-dbcp-1.4.jar;D:Sourcemavenrepositorycommons-poolcommons-pool1.6commons-pool-1.6.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 com.bdqn.SysUserTest,testGetUserList 
[DEBUG] 2021-05-17 01:14:18,457 com.bdqn.SysUserTest - testGetUserList account: zhaogang and realName: 赵刚 and roleId: 2 and roleName: 店长 and address: 北京市丰台区管庄新月小区 
 
Process finished with exit code 0 

Spring整合MyBatis配置总结

配置DAO及优化方式有以下四种:

  1. SqlSessionTemplate MyBatis-Spring提供了SqlSessionTemplate类,继承了SqlSession接口,操作数据库
  2. SqlSessionDaoSupport MyBatis-Spring提供了通过this.getSqlSession()方法获得SqlSession实例操作数据库,不需要定义SqlSession对象,使用起来更方便
  3. MapperFactoryBean MyBatis-Spring提供的MapperFactoryBean能够以配置的方式生成映射器的实现类,并注入给业务组件,无需编写DAO实现类
  4. MapperScannerConfig MyBatis-Spring提供的MapperScannerConfigurer将递归扫描基准包(包括各层级子包)下所有接口。如果他们在SQL映射文件中定义过,则将它们动态注册为映射器实现类,即可批量生成映射器的实现类了

         

 二、配置声明式事务

何为事务?

事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。就是把一系列的操作当成原子性去执行。

事务的四个属性ACID:

  1. 原子性(Atomicity)事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
  2. 一致性(Consistency)一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
  3. 隔离性(Isolation)可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
  4. 持久性(Durability)事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

实现事务的分类:

  • 编程式事务管理 

    将事务管理代码嵌到业务方法中来控制事务的提交和回滚

    缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

  • 声明式事务管理一般情况下比编程式事务好用。将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。将事务管理作为横切关注点,通过AOP方法模块化。Spring中通过Spring AOP框架支持声明式事务管理

Spring中如何配置声明式事务?

准备工作

SysUserMapper.java 接口增加 add(SysUser sysUser) 方法
package com.onc.dao;

import com.onc.pojo.SysUser;

import java.util.List;


public interface SysUserMapper {

    // 省略其他代码...

    
    public int add(SysUser sysUser);
}

SysUserService.java 接口增加 add(SysUser sysUser) 方法
package com.onc.service;


import com.onc.pojo.SysUser;

import java.util.List;


public interface SysUserService {

    // 省略其他代码...

    
    public boolean add(SysUser sysUser);
}

SysUserServiceImpl.java 实现类增加 add(SysUser sysUser) 方法
package com.bdqn.service;

import com.onc.dao.SysUserMapper;
import com.onc.pojo.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service("sysUserService") // 注册为一个Service层的Bean
public class SysUserServiceImpl implements SysUserService {

    @Autowired // @Resource // 使用注解的方式将DAO层的Bean注入
    private SysUserMapper sysUserMapper;

    
    // @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public boolean add(SysUser sysUser) {
        // 模拟在一个事务中两次对数据库的操作,第一次操作完成之后发生异常时,第二次未操作未执行,第一次操作也将回滚。两次操作要么都不成功,要么同时成功
        sysUserMapper.add(sysUser);
        int num = 5 / 0; // 模拟程序中抛出异常
        // if (sysUser != null) {
            // 手动抛出异常
            // throw new SendEMailException("发送通知邮件异常");
        // }
        sysUserMapper.add(sysUser);
        return true;
    }

}

SysUserTest.java 测试类中增加 testAddUser 方法
package com.onc;

import com.onc.pojo.SysUser;
import com.onc.service.SysUserService;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class SysUserTest {

    // 省略其他代码...

    
    @Test
    public void testAddUser() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SysUserService userService = (SysUserService) ctx.getBean("sysUserService");
        SysUser user = new SysUser();
        user.setAccount("test001");
        user.setRealName("测试用户001");
        user.setPassword("1234567");
        Date birthday = null;
        try {
            birthday = new SimpleDateFormat("yyyy-MM-dd").parse("2000-05-17");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setBirthday(birthday);
        user.setAddress("地址测试");
        user.setSex(1);
        user.setPhone("13688783697");
        user.setRoleId(1);
        user.setCreatedUserId(1);
        user.setCreatedTime(new Date());
        boolean isok = userService.add(user);
    
        logger.debug("testAdd result: " + isok);
    }

}

方式一:编写配置的方式进行事务配置

第一步 导入命名空间

该步骤在IDEA中可通过在编写配置节点时,通过Alt+Enter快捷键自动导入。

applicationContext.xml


第二步 定义事务管理器

事务管理器提供了对事务处理的全面支持和统一管理,相当于AOP中增强处理的角色。配置方式如下:

applicationContext.xml




    
    

这里使用Spring框架提供的事务管理器类DataSourceTransactionManager。需要注意的是,配置DataSourceTransactionManager时,要为其注入事先定义好的数据源组件。

除此之外,在不同编程环境中还有以下事务配置方式:


    



    



    

第三步 设置事务属性

事务管理器可以通过设定事务的属性为不同的业务方法指定具体的事务规则。

applicationContext.xml


    
        
        
        
        
        
        
        
        
        
        
        
        
    

注意:这里通过标签配置事务增强,其中transaction-manager属性的默认值是transactionManager。也就是说,如果定义的事务管理器Bean名称是transactionManager,则可以不指定该属性值。

可以在标签中配置事务的传播机制,隔离级别等属性,这些属性通过标签下的标签进行设置。标签中的name属性是必需的,用于指定匹配的方法,通配符(*)表示任意字符匹配,其他属性均为可选配置。具体特点和用法如下:

name

哪些方法需要有事务控制,支持 * 通配符

propagation

事务传播机制(通常情况下,第1种和第2种用的比较多)

  1. REQUIRED 如果有事务在运行,当前的方法就在这个事务内运行,否则就开启一个新的事务,并在自己的事务内运行,默认传播行为
  2. REQUIRED_NEW 当前方法必须启动新事务,并在自己的事务内运行,如果有事务正在运行,则将它挂起
  3. SUPPORTS 如果有事务在运行,当前的方法就在这个事务内运行,否则可以不运行在事务中
  4. NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
  5. MANDATORY 当前的方法必须运行在事务内部,如果没有正在运行的事务,就会抛出异常
  6. NEVER 当前方法不应该运行在事务中,如果有运行的事务,就抛出异常
  7. NESTED 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样

isolation

事务隔离级别,并发事务会导致发生以下三种类型的问题

  • 脏读 发生在一个事务读取了另一个事务改写尚未提交的数据时,改写的数据被回滚了,那么第一个事务获取的数据无效
  • 不可重复读 当同一个事务执行两次及以上相同的查询时,每次都得到不同的数据。一般因为另一并发事务在两次查询期间进行了更新
  • 幻读 第一个事务读取了一些数据,此时第二个事务在该表中插入了一些新数据,这时第一个事务再读取相同的数据就会多出几行

不可重复读和幻读的区别:不可重复读侧重点在相同数据被修改,而幻读是删除或新增

从理论上讲,事务应该完全隔离,避免并发事务导致的问题,但是这样可能对性能产生极大影响,因为事务必须按顺序进行了。所以在实际的开发中,为了提升性能,事务会以比较低的隔离级别运行。Spring中事务的隔离级别可以通过隔离属性指定:

  1. DEFAULT 使用底层数据库的默认隔离级别,大部分数据库,默认隔离级别都是READ_COMMITED
  2. READ_COMMITED 只允许事务读取已经被其他事务提交的更改,可以避免脏读,但不可重复读和幻读问题仍然可能出现
  3. READ_UNCOMMITED 允许事务读取未被其他事务提交的更改。效率最高,脏读、不可重复读、幻读都可能会出现
  4. REPEATABLE_READ 确保事务可以多次从一个字段中读取相同的值。在这个事务持续期间,禁止其他事务对这个字段进行更新
  5. SERIALIZABLE 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入,更新,删除。所有的并发问题都能避免,最安全,但是性能比较低

注意:事务的隔离级别需要底层数据库引擎的支持,而不是应用程序或者框架的支持

Oracle支持2种事务隔离级别:READ_COMMITED、SERIALIZABLE

MySQL支持4种事务隔离级别:READ_COMMITED、READ_UNCOMMITED、REPEATABLE_READ、SERIALIZABLE

 timeout

事务超时时间

允许事务运行的最长时间,以秒(s)为单位,超过给定的时间自动回滚,防止事务执行时间过长而影响系统性能。该属性需要底层的实现支持。默认值为-1,表示不超时

readonly

Boolean值,是否是只读事务

  1. 如果为true,告诉数据库此事务为只读事务。数据库优化,会对性能有一定提升,所以只要是查询的方法,建议设置为true
  2. 如果为 false(默认值),表示需要提交的事务。建议新增、修改、删除

 rollback-for

能够触发回滚的异常类型

Spring框架默认只在抛出RuntimeException时才标识事务回滚,可通过全限定类名自行指定需要回滚事务的异常,多个类名用英文逗号(,)隔开

 no-rollback-for

不触发回滚的异常类型

Spring框架默认CheckedException不会触发事务回滚,可通过全限定类名自行指定需要回滚事务的异常,多个类名用英文逗号隔开

第四步 定义事务切面

通过定义切面,可以将事务规则应用到指定的方法上。

applicationContext.xml


    
    
    
    

注意:这里通过标签的advice-ref属性引用标签设定的事务属性组件。

 至此,Spring框架的声明式事务通过以上四个步骤配置完成。

applicationContext.xml声明式事务完整配置




    
    






    
        
        
        
        
        
        
        
        
        
        
        
        
    



    
    
    
    

其中,com.bdqn.common.SendEMailException是自定义异常类型,表示发送邮件时发生的异常。代码如下:

SendEMailException.java

package com.onc.common;


public class SendEMailException extends RuntimeException {

   private static final long serialVersionUID = 1L;

   public SendEMailException(String message) {
      super(message);
   }

   public SendEMailException(Throwable cause) {
      super(cause);
   }

   public SendEMailException(String message, Throwable cause) {
      super(message, cause);
   }

   public SendEMailException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
      super(message, cause, enableSuppression, writableStackTrace);
   }

}

方式二:使用注解进行事务配置

除了使用配置文件处理事务外,Spring框架还支持注解配合少量配置的方式处理声明式事务,相对于纯配置文件的方式,这种方式所写的代码要简洁很多。

applicationContext.xml使用注解进行事务配置



    
    



配置文件编写完成之后,就可以在代码中使用 @Transactional 注解处理事务

SysUserServiceImpl.java
package com.onc.service;

import com.onc.dao.SysUserMapper;
import com.onc.pojo.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Transactional
@Service("sysUserService")
public class SysUserServiceImpl implements SysUserService {

    @Autowired // @Resource
    private SysUserMapper sysUserMapper;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List getList(SysUser sysUser) {
        try {
            return sysUserMapper.selectSysUserList(sysUser);
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw e;
        }
    }

    
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public boolean add(SysUser sysUser) {
        // 模拟在一个事务中两次对数据库的操作,第一次操作完成之后发生异常时,第二次未操作未执行,第一次操作也将回滚。两次操作要么都不成功,要么同时成功
        sysUserMapper.add(sysUser);
        int num = 5 / 0; // 模拟程序中抛出异常
        
        sysUserMapper.add(sysUser);
        return true;
    }

    public SysUserMapper getSysUserMapper() {
        return sysUserMapper;
    }

    public void setSysUserMapper(SysUserMapper sysUserMapper) {
        this.sysUserMapper = sysUserMapper;
    }

}

测试事务

当执行添加测试时,要么两次add操作同时成功,要么同时失败。测试代码如下:

SysUserTest.java执行testAddUser()方法

package com.onc;

import com.onc.pojo.SysUser;
import com.onc.service.SysUserService;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class SysUserTest {

    private Logger logger = Logger.getLogger(SysUserTest.class);

    @Before
    public void setUp() throws Exception {
    }

    
    @Test
    public void testGetUserList() {
        // 多配置文件,同时加载;也可以在主配置文件applicationContext.xml中导入其他配置(推荐)
        // String[] confs = {"applicationContext.xml","applicationContext-dao.xml","applicationContext-service.xml"};
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SysUserService userService = (SysUserService) ctx.getBean("sysUserService");
        List userList = new ArrayList();
        SysUser sysUser = new SysUser();
        sysUser.setRealName("赵");
        sysUser.setRoleId(2);
        userList = userService.getList(sysUser);

        for (SysUser userResult : userList) {
            logger.debug("testGetUserList account: "
                    + userResult.getAccount() + " and realName: "
                    + userResult.getRealName() + " and roleId: "
                    + userResult.getRoleId() + " and roleName: "
                    + userResult.getRoleIdName() + " and address: "
                    + userResult.getAddress());
        }
    }

    
    @Test
    public void testAddUser() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SysUserService userService = (SysUserService) ctx.getBean("sysUserService");
        SysUser user = new SysUser();
        user.setAccount("test001");
        user.setRealName("测试用户001");
        user.setPassword("1234567");
        Date birthday = null;
        try {
            birthday = new SimpleDateFormat("yyyy-MM-dd").parse("2000-05-17");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setBirthday(birthday);
        user.setAddress("地址测试");
        user.setSex(1);
        user.setPhone("13688783697");
        user.setRoleId(1);
        user.setCreatedUserId(1);
        user.setCreatedTime(new Date());
        boolean isok = userService.add(user);

        logger.debug("testAdd result: " + isok);
    }

}

执行测试用例,查看数据库的数据,发现事务起作用了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/356041.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号