周振林 周振林
首页
  • 前端文章

    • HTML
    • CSS
    • Tailwind CSS (opens new window)
    • JavaScript
    • Vue3
    • 其他
  • Spring
  • SpringMVC
  • Mybatis
  • 安装教程
  • 其他教程
  • 基础
  • 虚拟化
  • Docker
  • OpenStack
  • 心情杂货
关于
收藏

周振林

IT界的小学生
首页
  • 前端文章

    • HTML
    • CSS
    • Tailwind CSS (opens new window)
    • JavaScript
    • Vue3
    • 其他
  • Spring
  • SpringMVC
  • Mybatis
  • 安装教程
  • 其他教程
  • 基础
  • 虚拟化
  • Docker
  • OpenStack
  • 心情杂货
关于
收藏
  • Spring

    • 接口设计规范
    • Spring IoC
    • Spring AOP
    • SpringBoot基础
    • SpringBoot 常用注解
    • SpringBoot Conditional注解
    • SpringBoot 组件注入方式
    • SpringBoot 组件Bean生命周期
    • SpringBoot自动配置原理
    • SpringBoot自定义Starter
    • SpringBoot其他功能
    • SpringBoot JdbcTemplate
      • SpringBoot事务
      • SpringBoot文档
      • SpringBoot Starter和BOM区别
      • SpringBoot集成Modbus实现设备
      • 查询优化N+1
      • Response设置响应编码
      • Thymeleaf教程
      • Maven教程
      • Tree工具类,轻松搞定树结构
      • 项目代码组织方式
    • SpringMVC

    • Mybatis

    • 安装教程

    • 其他教程

    • 后端
    • Spring
    周振林
    2025-11-21
    目录

    SpringBoot JdbcTemplate

    # JdbcTemplate

    实验 内容 目标
    实验1 按照id查询图书 了解 queryForObject
    实验2 新增一个图书 了解 update
    实验3 按照id修改图书库存
    实验4 按照id删除图书
    实验5 按照username扣减账户余额 准备事务环境
    实验6 编写用户购买图书完整方法

    # SQL文件

    创建数据库spring_tx

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for account
    -- ----------------------------
    DROP TABLE IF EXISTS `account`;
    CREATE TABLE `account`  (
      `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '用户id',
      `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
      `age` int(0) NULL DEFAULT NULL COMMENT '年龄',
      `balance` decimal(10, 2)  NULL DEFAULT NULL COMMENT '余额',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of account
    -- ----------------------------
    INSERT INTO `account` VALUES (1, 'zhangsan', 18, 10000.00);
    INSERT INTO `account` VALUES (2, 'lisi', 20, 10000.00);
    INSERT INTO `account` VALUES (3, 'wangwu', 16, 10000.00);
    
    -- ----------------------------
    -- Table structure for book
    -- ----------------------------
    DROP TABLE IF EXISTS `book`;
    CREATE TABLE `book`  (
      `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '图书id',
      `bookName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图书名',
      `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '单价',
      `stock` int(0) NULL DEFAULT NULL COMMENT '库存量',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of book
    -- ----------------------------
    INSERT INTO `book` VALUES (1, '剑指Java', 100.00, 100);
    INSERT INTO `book` VALUES (2, '剑指大数据', 100.00, 100);
    INSERT INTO `book` VALUES (3, '剑指Offer', 100.00, 100);
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42

    # POM.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>annotationProcessor</scope>
    </dependency>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    # 配置文件

    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/spring_tx
        username: root
        password: 123456
    
    1
    2
    3
    4
    5
    6

    # Account类

    @Data
    public class Account {
        private Integer id;
        private String username;
        private Integer age;
        private BigDecimal balance;
    }
    
    1
    2
    3
    4
    5
    6
    7

    # Book类

    @Data
    public class Book {
        private Integer id;
        private String bookName;
        private BigDecimal price;
        private Integer stock;
    }
    
    1
    2
    3
    4
    5
    6
    7

    # AccountDao类

    @Component
    public class AccountDao {
    
        @Autowired
        JdbcTemplate jdbcTemplate;
    
        /**
         * 按照username扣减账户余额
         * @param username 用户名
         * @param delta 扣减的金额
         */
        //@Transactional(propagation = Propagation.REQUIRED,timeout = 5)
        public void updateBalanceByUsername(String username, BigDecimal delta) throws InterruptedException {
            String sql = "update account set balance = balance - ? where username = ?";
            // 执行SQL
    //        Thread.sleep(4000);
            jdbcTemplate.update(sql, delta, username);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    # BookDao类

    @Component
    public class BookDao {
    
        @Autowired
        JdbcTemplate jdbcTemplate;
    
    
        /**
         * 按照id查询图书
         * @param id
         * @return
         */
        @Transactional
        public Book getBookById(Integer id) {
    
            //1、查询图书SQL
            String sql = "select * from book where id  = ?";
            //2、执行查询
            Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
            return book;
        }
    
    
    
        // REPEATABLE_READ: 可重复读。 快照读。 MySQL默认
        // READ_COMMITTED: 读已提交。 当前读。 Oracle默认
        //@Transactional(isolation = Isolation.REPEATABLE_READ)
        public BigDecimal getBookPrice(Integer id){
            String sql = "select price from book where id=?";
            //BigDecimal decimal1 = jdbcTemplate.queryForObject(sql, BigDecimal.class, id);
    
            //BigDecimal decimal2 = jdbcTemplate.queryForObject(sql, BigDecimal.class, id);
    
            //BigDecimal decimal3 = jdbcTemplate.queryForObject(sql, BigDecimal.class, id);
    
            //BigDecimal decimal4 = jdbcTemplate.queryForObject(sql, BigDecimal.class, id);
    
            //BigDecimal decimal5 = jdbcTemplate.queryForObject(sql, BigDecimal.class, id);
    
            return jdbcTemplate.queryForObject(sql,BigDecimal.class,id);
        }
    
    
        /**
         * 添加图书
         * @param book
         */
        public void addBook(Book book){
            String sql = "insert into book(bookName,price,stock) values (?,?,?)";
            jdbcTemplate.update(sql,book.getBookName(),book.getPrice(),book.getStock());
        }
    
    
        /**
         * 按照图书id修改图书库存
         * @param bookId 图书id
         * @param num  要减几个
         */
        //@Transactional(propagation = Propagation.REQUIRES_NEW)
        public void updateBookStock(Integer bookId,Integer num){
            String sql = "update book set stock=stock-? where id=?";
            jdbcTemplate.update(sql,num,bookId);
    //        int i = 10/0;
        }
    
    
        /**
         * 按照id删除图书
         * @param id
         */
        public void deleteBook(Integer id){
            String sql = "delete from book where id=?";
            jdbcTemplate.update(sql,id);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75

    # AccountDaoTest测试类

    @SpringBootTest
    public class AccountDaoTest {
    
        @Autowired
        AccountDao accountDao;
    
        @Autowired
        UserService userService;
    
        @Autowired
        TransactionManager transactionManager;
    
    
        @Test
        void testTM(){
            System.out.println("transactionManager = " + transactionManager);
            System.out.println(transactionManager.getClass());
        }
    
    
        //测试结账
        @Test
        void testcheckout() throws Exception {
            userService.checkout("wangwu",3,4);
        }
    
        @Test
        void testUpdate() throws InterruptedException {
            accountDao.updateBalanceByUsername("zhangsan", new BigDecimal(9.9));
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    # BookDaoTest测试类

    @SpringBootTest
    class BookDaoTest {
    
        @Autowired
        DataSource dataSource;
    
    
        @Autowired
        JdbcTemplate jdbcTemplate; 
        
        @Autowired
        BookDao bookDao;
    
    
        @Test
        void testDelete() {
            bookDao.deleteBook(4);
        }
    
    
        @Test
        void testUpdate() {
            bookDao.updateBookStock(4,2);
        }
    
        @Test
        void testAdd() {
            Book book = new Book();
            book.setBookName("西游记");
            book.setPrice(new BigDecimal("19.9"));
            book.setStock(100);
            bookDao.addBook(book);
        }
        
        @Test
        void testQuery(){
            Book bookById = bookDao.getBookById(1);
            System.out.println("bookById = " + bookById);
        }
    
        @Test
        void contextLoads() throws SQLException {
            // HikariDataSource;
            // DruidDataSource;
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
    
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    Last Updated: 2025/11/21, 16:34:23
    SpringBoot其他功能
    SpringBoot事务

    ← SpringBoot其他功能 SpringBoot事务→

    最近更新
    01
    查询优化N+1
    12-02
    02
    项目代码组织方式
    12-02
    03
    Mybatis分页插件
    12-02
    更多文章>
    Copyright © 2019-2025 鲁ICP备19032096号-1
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式
    ×