之前帮同学做个app的后台,使用了MySQL+MyBatis,遇到了一个查询提交的问题,卡了很久,现在有时间了来复盘下

环境情况

假设有学生表:

USE test;
CREATE TABLE `student` (
Id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
Name varchar(20) NOT NULL,
Grade int NOT NULL
)

mybatis项目目录的大致结构为:

+---src
| +---main
| | +---java
| | | | Test.java
| | | |
| | | +---pojo
| | | | Student.java
| | | |
| | | \---dao
| | | IStudentDao.java
| | |
| | \---resources
| | | log4j.properties
| | | mybatis-config.xml
| | |
| | \---mappers
| | StudentMapper.xml

Test.java

import dao.IStudentDao;
import pojo.Student; import java.io.InputStream; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class Test {
public static void main(String args[]) throws Exception{
String resource ="mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
IStudentDao studentDAO = sqlSession.getMapper(IStudentDao.class);
Student currentStudent; currentStudent = studentDAO.getStudentById(1);
System.out.println(currentStudent); Thread.sleep(1000 * 30); currentStudent = studentDAO.getStudentById(1);
System.out.println(currentStudent);
}
}

Student.java

package pojo;

public class Student {
private int id;
private String name;
private int grade; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return this.name;
} public void setName(String name) {
this.name = name;
} public int getGrade() {
return this.grade;
} public void setGrade(int grade) {
this.grade = grade;
} @Override
public String toString(){
return
"id = " + id + "\t" + "name = " + name + "\t" + "grade = " + grade + "\t";
}
}

IStudentDao

package dao;

import org.apache.ibatis.annotations.Param;
import pojo.Student; public interface IStudentDao {
public Student getStudentById(@Param("studentId") int studentId);
}

mybatis-config.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>
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="nihaonihao123123"/>
</properties> <environments default="test">
<environment id="test">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="mappers/StudentMapper.xml"></mapper>
</mappers>
</configuration>

StudentMapper.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">
<mapper namespace="dao.IStudentDao">
<select id="getStudentById" resultType="pojo.Student">
SELECT id AS id, name AS name, grade AS grade
FROM student
WHERE id = #{studentId} ;
</select>
</mapper>

问题复盘

在第一次查询后,主线程暂停30秒,此时在MySQL WorkBench中修改了原来的数据,将“张三”变成“张三123”,主线程恢复后数据并没有任何变化。

开始以为是缓存问题,遂在mybatis-config.xml中禁用一级缓存:在configuration标签中,在 properties标签之后加入

<settings>
<setting name="localCacheScope" value="STATEMENT"/>
</settings>

问题依旧(注意看时间的变化,确实进行了更新,查询的数据确实没有变化)

16:03:43	UPDATE test.student SET name = '张三123' WHERE id = 1	1 row(s) affected Rows matched: 1  Changed: 1  Warnings: 0	0.062 sec

开启mysql的查询日志比较差别

mysql> set GOLBAL general_log=on;
mysql> show variables like %general%;

注意:在我们的MyBatis中autocommit被设置为0,MySQL WorkBench中autocommit被设置为1

此时重新还原数据库数据,在Test.java手工加入提交

currentStudent = studentDAO.getStudentById(1);
sqlSession.commit();
System.out.println(currentStudent);

依然无效!!!

回顾一下,自动提交的问题确实存在,思路并没有问题。因此查询mybatis文档。

需要加入强制提交参数 true

currentStudent = studentDAO.getStudentById(1);
sqlSession.commit(true);
System.out.println(currentStudent);

加入后得到正确结果\:

总结

在MySQL中,查询也是一次事务,如果没有提交,则每次查询的结果都是相同的。然而建议的还是关闭自动提交(autocommit=0,但MySQL还是会自动开启一个事务,只是不提交),这样在向多个表中写数据时可以保证一致性;对于增删改操作而言,(在单个客户端中)可以在确认执行后的数据正确,再提交,相当于提前模拟一遍。

MySQL中的查询事务问题的更多相关文章

  1. mysql中模糊查询的四种用法介绍

    下面介绍mysql中模糊查询的四种用法: 1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] ...

  2. 【原创】7. MYSQL++中的查询结果获取(各种Result类型)

    在本节中,我将首先介绍MYSQL++中的查询的几个简单例子用法,然后看一下mysqlpp::Query中的几个与查询相关的方法原型(重点关注返回值),最后对几个关键类型进行解释. 1. MYSQL++ ...

  3. mysql中如何查询最近24小时、top n查询

    MySQL中如何查询最近24小时. where visittime >= NOW() - interval 1 hour; 昨天. where visittime between CURDATE ...

  4. Mysql中分页查询两个方法比较

    mysql中分页查询有两种方式, 一种是使用COUNT(*)的方式,具体代码如下 1 2 3 SELECT COUNT(*) FROM foo WHERE b = 1;   SELECT a FROM ...

  5. mysql中in查询中排序

    mysql中in查询条件的时候,很多时候排序是不规则的,如何按照in里面的条件进行排序呢? mysql中给出了办法,在in后面加order by field,order by field的首个条件是按 ...

  6. mysql 中合并查询结果union用法 or、in与union all 的查询效率

    mysql 中合并查询结果union用法 or.in与union all 的查询效率 (2016-05-09 11:18:23) 转载▼ 标签: mysql union or in 分类: mysql ...

  7. 下面介绍mysql中模糊查询的四种用法:

    下面介绍mysql中模糊查询的四种用法: 1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] ...

  8. 【面经】面试官:如何以最高的效率从MySQL中随机查询一条记录?

    写在前面 MySQL数据库在互联网行业使用的比较多,有些小伙伴可能会认为MySQL数据库比较小,存储不了很多的数据.其实,这些小伙伴是真的不了解MySQL.MySQL的小不是说使用MySQL存储的数据 ...

  9. 如何使用python将MySQL中的查询结果导出为Excel----xlwt的使用

    如何在MySQL中执行的一条查询语句结果导出为Excel? 一.可选方法 1.使用sql yog等远程登录,执行查询语句并导出结果集为Excel 适用于较简单的查询结果集的导出 如果需要多个SQL语句 ...

随机推荐

  1. Check Directory Existence in Shell

    The following command in one line can check if a directory exists. You can check the return value (& ...

  2. FIFO 深度了解

    嘻哈第二篇,深度聊聊各种细节. 优化与跨时钟阈分析

  3. PostgreSQL 时间转换

    背景:最近频繁使用到时间转换相关的操作,特此小记. 1.实时取最近24小时内数据. select now() - interval '24h'; 通过sql获得符合要求的时间段,当做where条件即可 ...

  4. Pikachu-XSS模块与3个案例演示

    一.概述 XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户. 形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致"精心构造"的字符输出在前端时被浏览 ...

  5. mysql--使用shardingsphere实现分表

    一. 简介 为什么要分表,无非就两个原因,要么是并发太高,要么就是数据量太大. 所谓分表就是把传统的单表扩展为多个数据结构一样的表,通过分表策略确定操作哪一张表. 我使用的分表规则是通过主键id进行取 ...

  6. SpringCloud升级之路2020.0.x版-19.Eureka的服务端设计与配置

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford Eureka Se ...

  7. Ubuntu18.04忘记root密码,重置root密码

    输入命令,更新root密码: sudo passwd root 然后输入新密码,再输入一次确认新密码,新密码更新完毕! 切换root账号: su 如下图所示,发现已经由zyw账号切换到root账号了!

  8. C# 检测某版本VC++是否安装

    一.根据微软的产品号GUID,调用msi.dll class Program { static void Main(string[] args) { if (GetProcuct("{GUI ...

  9. SpringCloud降级熔断 Hystrix

    1.分布式核心知识之熔断.降级讲解 简介:系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案 1.熔断:         保险丝,熔断服务,为了防止整个系统故障,包含子和下游服务 下单服 ...

  10. 了解Prometheus

    了解Prometheus 标签(空格分隔): 监控 介绍 Prometheus是用来收集和存储服务器的实时数据(比如:CPU.硬盘.服务响应.日志等),通过其丰富的运算函数,可以计算得到很多的服务性能 ...