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: shaofeer@163.com
* <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: shaofeer@163.com
* <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: shaofeer@163.com
* <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: shaofeer@163.com
* <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: shaofeer@163.com
* <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();
}
感謝查閱,希望對你有所幫助。如博文存在錯誤,請及時指出,我會立即更改。謝謝!歡迎大家關注我的微信公眾號《趣學程序》獲取更多……