mybatis的mapper文件中的一个标签是否可以写多条SQL语句?是否存在事物?
这篇博文的由来,朋友面试遇到两个问题?
第一个问题是mybatis的mapper文件中的一个标签是否可以写多条SQL语句?
第二个问题是上述问题如果成立,那么这个标签内是否存在事物?
数据库事物的四大特性
回顾知识:
ACID
原子性、一致性、隔离性、持久性
问题答案
第一问题:mybatis的mapper文件中的一个标签可以写多条SQL语句
第二问题:标签中不存在事物
验证答案
一、创建数据库表
Create Table CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, `age` int(3) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4
二、搭建SpringBoot+Mybatis项目(略)
数据库配置:
默认的数据库连接配置基本上都是如下的:
url: jdbc:mysql://XXX.XXX.XXX.XXX:XXX/XXXX
这样默认是不能实现mybatis的mapper文件中的一个标签可以写多条SQL语句的,会报异常:
Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
如果遇到上述异常我们可以通过对数据库连接的URL添加参数,从而实现可以执行多条SQL语句的功能。
url: jdbc:mysql://XXX.XXX.XXX.XXX:XXX/XXXX?allowMultiQueries=true
三、编写MVC三层代码
MyTest.java
package com.staryea.sfdemo.module.entity; import lombok.Data; /** * @author: shaofeer * <p> * @qq: 337081267 * <p> * @CSDN: http://blog.csdn.net/pyfysf * <p> * @blog: http://wintp.top * <p> * @email: * <p> * @time: 2020/5/9 */ @Data public class MyTest { private Integer id; private String name; private Integer age; }
MyTestMapper.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="com.staryea.sfdemo.module.mapper.MyTestMapper"> <!--下面这个语句是正确的 为了测试是否可以同时执行多条SQL--> <select id="selectBatchSql"> INSERT INTO `test` ( `name`, `age`) VALUES ( ‘shaofeer‘, 10); INSERT INTO `test` (`name`, `age`) VALUES ( ‘pyfysf‘, ‘20‘); INSERT INTO `test` (`name`, `age`) VALUES (‘upuptop‘, 10); </select> <!--下面这个语句是错误的 为了测试是否存在事物--> <delete id="deleteBatchSql"> INSERT INTO `test` ( `name`, `age`) VALUES ( ‘shaofeer‘, 10); INSERT INTO `test` (`name`, `age`) VALUES ( ‘pyfysf‘, ‘pyfysf‘); INSERT INTO `test` (`name`, `age`) VALUES (‘upuptop‘, 10); </delete> </mapper>
MyTestMapper.java
package com.staryea.sfdemo.module.mapper; /** * @author: shaofeer * <p> * @qq: 337081267 * <p> * @CSDN: http://blog.csdn.net/pyfysf * <p> * @blog: http://wintp.top * <p> * @email: * <p> * @time: 2020/5/9 */ public interface MyTestMapper { void selectBatchSql(); void deleteBatchSql(); }
MyTestService.java
package com.staryea.sfdemo.module.service; /** * @author: shaofeer * <p> * @qq: 337081267 * <p> * @CSDN: http://blog.csdn.net/pyfysf * <p> * @blog: http://wintp.top * <p> * @email: * <p> * @time: 2020/5/9 */ public interface MyTestService { void selectBatchSql(); void deleteBatchSql(); }
MyTestServiceImpl.java
package com.staryea.sfdemo.module.serviceimpl; import com.staryea.sfdemo.module.mapper.MyTestMapper; import com.staryea.sfdemo.module.service.MyTestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author: shaofeer * <p> * @qq: 337081267 * <p> * @CSDN: http://blog.csdn.net/pyfysf * <p> * @blog: http://wintp.top * <p> * @email: * <p> * @time: 2020/5/9 */ @Service public class MyTestServiceImpl implements MyTestService { @Autowired MyTestMapper mMyTestMapper; @Override public void selectBatchSql() { mMyTestMapper.selectBatchSql(); } @Override public void deleteBatchSql() { mMyTestMapper.deleteBatchSql(); } }
MyTestController.java
package com.staryea.sfdemo.module.controller; import com.staryea.sfdemo.module.service.MyTestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author: shaofeer * <p> * @qq: 337081267 * <p> * @CSDN: http://blog.csdn.net/pyfysf * <p> * @blog: http://wintp.top * <p> * @email: * <p> * @time: 2020/5/9 */ @RestController @RequestMapping("/test") public class MyTestController { @Autowired MyTestService mMyTestService; @RequestMapping(value = "deleteBatchSql") public String deleteBatchSql() { mMyTestService.deleteBatchSql(); return "deleteBatchSql"; } @RequestMapping(value = "selectBatchSql") public String selectBatchSql() { mMyTestService.selectBatchSql(); return "selectBatchSql"; } }
四、启动服务器
- 验证mapper单个标签可以执行多条SQL
浏览器中输入项目的访问地址,进行测试。
浏览器访问(因人而异):http://localhost:9898/test/selectBatchSql
查看数据库是否成功插入。
- 验证mapper单个标签执行多条SQL时,不存在数据库事物
浏览器访问(因人而异):http://localhost:9898/test/deleteBatchSql
我们会发现后端控制台报异常了
### Error updating database. Cause: java.sql.SQLException: Incorrect integer value: ‘pyfysf‘ for column ‘age‘ at row 1 ###
如果存在数据库事物,那么三条语句都不会成功插入到数据库。
通过查看数据库表数据,第一条语句成功执行了,第二条和第三条语句都没有执行成功,说明mybatis的mapper文件中的一个标签执行多条SQL语句时,不存在数据库事物
五、 注意
如果在Service层的方法上添加@Transactional
注解之后,则标签有事物!
@Transactional @Override public void deleteBatchSql() { mMyTestMapper.deleteBatchSql(); }
感谢查阅,希望对你有所帮助。如博文存在错误,请及时指出,我会立即更改。谢谢!欢迎大家关注我的微信公众号《趣学程序》获取更多……