1

Spring Boot - 数据库配置

回顾

  1. Spring Boot - 初识 Hello World
  2. Spring Boot - Servlet、过滤器、监听器、拦截器
  3. Spring Boot - 静态资源处理、启动加载、日志处理

整合JdbcTemplate

  1. pom.xml配置maven依赖
  2. application.properties配置数据源
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=1
spring.datasource.initial-size=1
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=18800
实践:查询用户表
  • 创建表user
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(8) NOT NULL DEFAULT '',
  `age` int(11) NOT NULL,
  `create` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
  • 创建用户实体
package com.wanye.entity;

/**
 * Created by wanye on 2017/6/3.
 */
public class User {
    private int id;
    private String name;
    private int age;
    private int create;
// 省略get set
}
  • 创建UserService并注入JdbcTemplate,实现查询⽅法
package com.wanye.service;

import com.wanye.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by wanye on 2017/6/3.
 */
@Service
public class UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<User> getUserList() {
        return jdbcTemplate.query("select * from user", new RowMapper<User>() {

            @Override
            public User mapRow(ResultSet resultSet, int i) throws SQLException {
                User user = new User();
                user.setId(resultSet.getInt("id"));
                user.setName(resultSet.getString("name"));
                user.setAge(resultSet.getInt("age"));
                user.setCreate(resultSet.getInt("create"));
                return user;
            }
        });
    }
}
    @Autowired
    private UserService userService;
    @RequestMapping("/userlist")
    public List<User> getUserList() {
        return userService.getUserList();
    }

整合MyBatis

  1. pom.xml配置maven依赖
  2. application.properties配置mybatis
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.2.0</version>
        </dependency>
        <!-- 省略mysql驱动依赖 -->
#关于mapper文件位置和entity类位置,大家需要按自己需要进行修改
mybatis.mapper-locations=classpath*:mapper/*Mapper.xml
mybatis.type-aliases-package=com.wanye.entity
实践:通过用户id查询指定用户信息
  • 创建mapper接口 @Mapper
package com.wanye.mapper;

import com.wanye.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 * Created by wanye on 2017/6/3.
 */
@Repository
@Mapper
public interface UserMapper {
    public User getUserById(int id);
}
  • 创建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要指向定义的mapper接口 -->
<mapper namespace="com.wanye.mapper.UserMapper">
<!-- id即mapper接口中的具体方法名 -->
<!-- resultType即方法返回值-->
    <select id="getUserById" resultType="com.wanye.entity.User">
        SELECT * FROM USER WHERE id = #{id}
    </select>
</mapper>
  • 实现查询⽅法,在userservice类中增加
    @Autowired
    private UserMapper userMapper;
    public User getUserById(int id) {
        return userMapper.getUserById(id);
    }
  • 在controller中返回Json结果,省略

事务

事务概念及原理
  1. 定义:从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简答的说就是:要么全部执行成功,要么撤销不执行。
  2. java事务:既然事务的概念从数据库而来,那Java事务是什么?之间有什么联系?实际上,一个Java应用系统,如果要操作数据库,则通过JDBC来实现的。增加、修改、删除都是通过相应方法间接来实现的,事务的控制也相应转移到Java程序代码中。因此,数据库操作的事务习惯上就称为Java事务。
  3. 实现原理(单机事务):JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法:
            public void setAutoCommit(boolean)  
            public boolean getAutoCommit()  
            public void commit()  
            public void rollback()  

使用 JDBC 事务时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。

  1. JTA(Java Transaction API)事务(多机事务),通过xa实现,需要驱动支持。事务可以跨越多个数据库或多个DAO,坑比较多,使用也比较复杂。
  2. 容器事务,由j2ee容器提供,基本上是基于JTA来实现。局限于EJB应用使用。
如何配置事务
  1. 使用注解 @EnableTransactionManagement 开启事务支持,建议在启动类上增加,例如
@EnableTransactionManagement
@SpringBootApplication
public class Start {
    public static void main(String[] args) {
        SpringApplication.run(Start.class, args);
    }
}
  1. 在访问数据库的Service方法上添加注解 @Transactional 便可
实践:实现拷贝用户信息,并将原用户的name修改为xiaoming
  1. Case1:正常(新增1条记录name=xiaohong,更新1条记录name=xiaoming)
  2. Case2:异常(name长度超出varchar(8))导致回滚

userService.java
@Transactional
public void copyUser(long id, String name) {
    User user = getUserById(id);
    int i = jdbcTemplate.update("insert INTO USER (name,age,`CREATE`) VALUES (?,?,?)", new Object[]{user.getName(), user.getAge(), user.getCreate()});
    logger.info("复制成功: i=" + i + " name=" + name + " id=" + id);
    i = jdbcTemplate.update("update USER SET name=? where id=?", new Object[]{name, user.getId()});
    logger.info("更新成功:i=" + i + " name=" + name + " id=" + id);
}
userController.java
@RequestMapping("/user/cp/{id}/{name}")
public List<User> cpUser(@PathVariable("id") long id, @PathVariable("name") String name) {
    userService.copyUser(id, name);
    return userList();
}

大家自行验证一下,如果{name}长度超过8个字节,会导致复制成功的数据回滚。另外,mysql数据库引擎需要使用InnoDB,并不是所有的引擎都支持事务,大家可以查询数据库引擎相关资料。

总结

  • 本文讲解Spring Boot整合JdbcTemplate、整合mybatis,介绍并重点讲解了事务处理和配置
  • 本文未提及关于分⻚查询和数据库连接池,我认为分页查询的重点是分页算法如何封装,并不是Spring Boot关注的重点,大家可以自己实现,
  • 另外现在常用的数据库连接池有c3p0/dbcp/tomcat-jdbc/HikariCP
  • 顺便提一下,在Spring Boot中更改数据源,只需要在application.properties配置文件中增加spring.datasource.type配置即可,例如:
spring.datasource.type=com.zaxxer.hikari.HikariDataSource

最后

如果觉得我的文章对您有用,请点赞、收藏。您的支持将鼓励我继续创作!为了提高大家学习效果,录制了同步的视频课程,还望大家支持视频课程

优惠报名

【全程撸码】Spring Boot 1.5 快速入门教程(全)(原价:28,优惠价:22)

【全程撸码】Spring Boot 进阶(全)(原价:46,优惠价:39)

预告

  1. Spring Boot - 部署Deploy
  2. Spring Boot - 整合jsp后必须通过spring-boot:run方式启动?

图片描述


刘忠旭
441 声望500 粉丝

致力于最实用的技术