mybatis使用datasourcetransactionmanager管理事务为啥不回滚

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis使用datasourcetransactionmanager管理事务为啥不回滚相关的知识,希望对你有一定的参考价值。

参考技术A 所以尽管 MyBatis3 提供了对 Spring 的整合,但是 org.springframework.jdbc.datasource.DataSourceTransactionManager 这个事务管理 器还是不支持

SSM框架Mybatis的基本使用

Mybatis的基本使用

学习目标

  1. 认识Mybatis

  2. 了解Mybatis功能

  3. 知道为什么学习Mybatis

  4. 利用Mybatis编写一个简单程序

  5. 学会使用Mybatis基本功能

  6. 了解Mybatis的基本配置

一、认识Mybatis

官方文档

1. 简介

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,屏蔽了jdbc api底层访问细节,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

2. 原理

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

3. 为什么使用Mybatis

原生jdbc连接

import org.junit.jupiter.api.Test;

import java.sql.*;


public class MySQLTest 
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/hist?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true" +
            "&serverTimezone=UTC";

    // 数据库的用户名与密码,需要根据自己的设置
    static final String USER = "root";
    static final String PASS = "123456";

    /**
     * 测试原生sql方式查询
     */
    @Test
    public void testQuery() 
        Connection conn = null;
        Statement stmt = null;
        try 
            // 1.注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 2.打开链接
            System.out.println("连接数据库...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            // 3.执行查询
            System.out.println(" 实例化Statement对象...");
            stmt = conn.createStatement();

            String sql;
            sql = "SELECT runoob_id, runoob_title, runoob_author FROM runoob_tbl WHERE runoob_title='学习PHP'";
            ResultSet rs = stmt.executeQuery(sql);

            // 4.展开结果集数据库
            while (rs.next()) 
                System.out.println(rs.getString("runoob_title"));
                // 通过字段检索
                int id = rs.getInt("runoob_id");
                String name = rs.getString("runoob_title");
                String author = rs.getString("runoob_author");

                // 输出数据
                System.out.print("ID: " + id);
                System.out.print("name: " + name);
                System.out.print("author: " + author);
                System.out.print("\\n");
            
            // 5.完成后关闭
            rs.close();
            stmt.close();
            conn.close();
         catch (Exception se) 
            // 处理 JDBC 错误
            se.printStackTrace();
        // 处理 Class.forName 错误
        finally 
            // 关闭资源
            try 
                if (stmt != null) 
                    stmt.close();
                
             catch (SQLException ignored) 
            // 什么都不做
            try 
                if (conn != null) 
                    conn.close();
                
             catch (SQLException se) 
                se.printStackTrace();
            
        
        System.out.println("Goodbye!");
    

<?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>org.example</groupId>
    <artifactId>jdbctest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

存在的问题

  1. 数据库连接频繁开启和关闭,会严重影响数据库的性能。

  2. 代码中存在硬编码,分别是数据库部分的硬编码和SQL执行部分的硬编码。

Mybatis的存在:

  • Mybatis就是帮助我们将数据存入数据库中 , 和从数据库中取数据

  • MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) -->对象关系映射

当然,所有的事情,不用Mybatis依旧可以做到,只是用了它,所有实现会更加简单!

4. Mybatis的优点

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。

  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。

  • 提供xml标签,支持编写动态sql。

  • 用户量大,公司需要

5. Mybatis的核心

  • mybatis配置文件,包括Mybatis****全局配置文件和Mybatis映射文件**,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。

  • mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。

  • 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。

  • SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)

  • Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括HashMap集合对象、POJO对象类型

6. 如何获取mybatis

  • Maven
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>
  • Github:https://github.com/mybatis/mybatis-3

  • 源码中文注释: https://github.com/tuguangquan/mybatis
    要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。

二、Mybatis入门

项目结构

1. 环境搭建

  • 创建数据库
CREATE DATABASE `mybatis_01`;

USE `mybatis_01`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`phone` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`name`,`phone`) values (1,'张三','1536537156'),(2,'李四','1536537157'),(3,'王五','1536537158');

新建一个Maven项目作为父工程

  • 导入相关Maven依赖
	<dependencies>
        <!--   mybatis依赖     -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!-- 数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!-- <version>5.1.47</version>-->
            <version>8.0.11</version>

        </dependency>
        <!--        <dependency>-->
        <!--            <groupId>mysql</groupId>-->
        <!--            <artifactId>mysql-connector-java</artifactId>-->
        <!--            <version>8.0.12</version>-->
        <!--        </dependency>-->
        <!--测试依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
    </dependencies>
    <!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

2. 创建一个模块,编写MyBatis核心配置文件

mybatis-config.xml

<?xml version="1.0" encoding="GBK" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置mybatis的环境信息 -->
    <environments default="development">
        <environment id="development">
            <!-- 配置JDBC事务控制,由mybatis进行管理 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源,采用传统的javax. sql. DataSource规范中的连接池 -->
            <dataSource type="POOLED">
                <!--       如果数据库驱动使用的是8.0.12需要使用下面的驱动        -->
                <!--<property name="driver" value="com.mysql.cj.jdbc.Driver"/>-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>

                <!--       如果数据库驱动使用的是8.0.12需要使用下面的配置         -->
                <!--<property name="url" value="jdbc:mysql://localhost:3306/mybatis_01?useSSL=false&amp;useUnicode=true&amp;serverTimezone=UTC&amp;characterEncoding=utf8"/>-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_01?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/hist/dao/UserMapper.xml"/>
    </mappers>
</configuration>

3. 编写MyBatis工具类

MybatisUtil

public class MybatisUtil 
    private static SqlSessionFactory sqlSessionFactory;

    static 
        try 
            // 1. 读取配置文件
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 2. 通过SqlSessionFactoryBuilder创建sqlSessionFactory会话工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
         catch (IOException e) 
            e.printStackTrace();
        
    

    /**
     *功能描述:获取SqlSession连接
    */
    public static SqlSession getSession()
        // 使用sqlSessionFactory创建SqlSession
        return sqlSessionFactory.openSession();
    

4. 创建实体类

User

public class User 
   
   private int id;  //id
   private String name;   //姓名
   private String phone;   //手机号
   
   //构造,有参,无参
   //set/get
   //toString()
   

5. 编写Mapper接口

public interface UserMapper 
    /**
     *功能描述: 查询用户集合
     * @return java.util.List<com.hist.entity.User>
    */
    List<User> selectUser();

6. 编写Mapper.xml配置文件

<?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">
<!-- 
	namespace:命名空间,它的作用就是对SQL进行分类化管理,可以理解为SQL隔离
	注意:使用mapper代理开发时,namespace有特殊且重要的作用
 -->

<mapper namespace="com.hist.dao.UserMapper">
    <select id="selectUser" resultType="com.hist.entity.User">
      select * from user
     </select>
</mapper>

7. 编写测试类

public class UserTest 
    @Test
    public void selectUser() 
        SqlSession session = MybatisUtil.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        // 调用SqlSession操作数据库
        List<User> users = mapper.selectUser();

        for (User user: users)
            System.out.println(user);
        
        // 关闭 SqlSession
        session.close();
    

8. 运行结果

三、更多案例讲解

1. 通过id查询用户

在UserMapper中添加方法

public interface UserMapper 
    /**
     *功能描述: 查询用户集合
     * @return java.util.List<com.hist.entity.User	>
    */
    List<User> selectUser();
    /**
     *功能描述: 通过id查询用户
     * @param id 用户id
     * @return com.hist.entity.User
    */
    User selectUserById(int id);

在UserMapper.xml中添加Select语句

<!-- 
		[id]:statement的id,要求在命名空间内唯一  
		[parameterType]:入参的java类型
		[resultType]:查询出的单条结果集对应的java类型
		[#]: 表示一个占位符?
		[#id]:表示该占位符待接收参数的名称为id。注意:如果参数为简单类型时,#里面的参数名称可以是任意定义
	 -->
	<select id="selectUserById" parameterType="int" resultType="com.hist.entity.User">
		SELECT * FROM USER WHERE id = #id
	</select>

在测试类中添加

    @Test
    public void tsetSelectUserByIdSSM框架Mybatis的基本使用

MyBatis的使用一(框架的搭建)

MyBatis学习总结——使用MyBatis对表执行CRUD操作(转载)

Mybatis:Mybatis的三种使用方式

MyBatis学习总结——使用MyBatis对表执行CRUD操作

MyBatis-----1.MyBatis简介和使用