Spring Boot - 数据库配置
回顾
整合JdbcTemplate
- pom.xml配置maven依赖
- 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;
}
});
}
}
- 增加Controller,并返回结果
代码片段如下,关于如何实现web接口,请参考Spring Boot - 初识 Hello World
@Autowired
private UserService userService;
@RequestMapping("/userlist")
public List<User> getUserList() {
return userService.getUserList();
}
整合MyBatis
- pom.xml配置maven依赖
- 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结果,省略
事务
事务概念及原理
- 定义:从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简答的说就是:要么全部执行成功,要么撤销不执行。
- java事务:既然事务的概念从数据库而来,那Java事务是什么?之间有什么联系?实际上,一个Java应用系统,如果要操作数据库,则通过JDBC来实现的。增加、修改、删除都是通过相应方法间接来实现的,事务的控制也相应转移到Java程序代码中。因此,数据库操作的事务习惯上就称为Java事务。
- 实现原理(单机事务):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 事务不能跨越多个数据库。
- JTA(Java Transaction API)事务(多机事务),通过xa实现,需要驱动支持。事务可以跨越多个数据库或多个DAO,坑比较多,使用也比较复杂。
- 容器事务,由j2ee容器提供,基本上是基于JTA来实现。局限于EJB应用使用。
如何配置事务
- 使用注解 @EnableTransactionManagement 开启事务支持,建议在启动类上增加,例如
@EnableTransactionManagement
@SpringBootApplication
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
}
- 在访问数据库的Service方法上添加注解 @Transactional 便可
实践:实现拷贝用户信息,并将原用户的name修改为xiaoming
- Case1:正常(新增1条记录name=xiaohong,更新1条记录name=xiaoming)
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
最后
如果觉得我的文章对您有用,请点赞、收藏。您的支持将鼓励我继续创作!为了提高大家学习效果,录制了同步的视频课程,还望大家支持视频课程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。