Spring Boot 入门之持久层篇(三)
一、前言
上一篇《Spring Boot 入门之 Web 篇(二)》介绍了 Spring Boot 的 Web 开发相关的内容,项目的开发离不开数据,因此本篇开始介绍持久层相关的知识。
二、整合 JdbcTemplate
2.1 添加依赖
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mysql 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2.2 配置数据库连接
在 application.properties 中添加:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=tiger
其中,可以不指定 driver-class-name,因为 spring boot 会自动识别 url。
2.3 测试
2.3.1 建表
在 MySQL 中创建名为 springboot 的数据库,在该库中创建 user 表:
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(64) NOT NULL,
`birthday` DATE NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3
;
2.3.2 建实体类
public class User implements Serializable{
private static final long serialVersionUID = -6249397911566315813L;
private Integer id;
private String username;
private String password;
private Date birthday;
}
setter 和 getter 方法此处省略。
2.3.3 dao 接口
接口和实现类如下:
public interface UserDao {
public int insert(User user);
public int deleteById(Integer id);
public int update(User user);
public User getById(Integer id);
}
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int insert(User user) {
String sql = "insert into user(id,username,password,birthday) values(?,?,?,?)";
return this.jdbcTemplate.update(
sql,
user.getId(),
user.getUsername(),
user.getPassword(),
user.getBirthday()
);
}
@Override
public int deleteById(Integer id) {
String sql = "delete from user where id = ?";
return this.jdbcTemplate.update(sql,id);
}
@Override
public int update(User user) {
String sql = "update user set password = ? where id = ?";
return this.jdbcTemplate.update(
sql,
user.getPassword(),
user.getId()
);
}
@Override
public User getById(Integer id) {
String sql = "select * from user where id = ?";
return this.jdbcTemplate.queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setBirthday(rs.getDate("birthday"));
return user;
}
},id);
}
}
2.3.4 测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserDaoTest {
@Autowired
private UserDao userDao;
@Test
public void testInsert() {
User user = new User();
user.setId(1);
user.setUsername("张三");
user.setPassword("zhangsan");
user.setBirthday(new Date());
int result = this.userDao.insert(user);
System.out.println(result);
}
@Test
public void testGetById() {
User user = this.userDao.getById(1);
System.out.println(user.getUsername());
}
@Test
public void testUpdate() {
User user = new User();
user.setId(1);
user.setPassword("zhangsan123");
this.userDao.update(user);
}
@Test
public void testDeleteById() {
int result = this.userDao.deleteById(1);
System.out.println(result);
}
}
测试结果省略...
如需打印日志,在日志配置文件中添加如下配置:
<logger name="org.springframework.jdbc.core.JdbcTemplate" level="debug"/>
三、整合 Spring-data-jpa
3.1 添加依赖
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- springboot,jpa 整合包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
3.2 配置数据库连接
在 application.properties 中添加:
# 数据库连接配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=tiger
# JPA 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
3.3 编码
3.3.1 建表
在 MySQL 中创建名为 springboot 的数据库,在该库中创建 role 表:
CREATE TABLE `role` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(10) NOT NULL,
`descr` VARCHAR(100) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
注意,主键 ID 为 AUTO_INCREMENT 自增。
3.3.2 建实体类
添加相应的注解
@Entity
public class Role implements Serializable{
private static final long serialVersionUID = 3926276668667517847L;
@Id
@GeneratedValue
private Integer id;
@Column
private String name;
@Column
private String descr;
}
setter 和 getter 方法此处省略。
3.3.3 Repository 接口
public interface RoleRepository extends JpaRepository<Role, Integer>{
}
3.3.4 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class RoleRepositoryTest {
@Autowired
private RoleRepository roleRepository;
@Test
public void testInsert() {
Role role = new Role();
role.setName("管理员");
role.setDescr("测试");
Role result = this.roleRepository.save(role);
System.out.println(result);
}
@Test
public void testFindOne() {
Role role = this.roleRepository.findOne(1);
System.out.println(role);
}
@Test
public void testUpdate() {
Role role = new Role();
role.setId(1);
role.setName("管理员");
role.setDescr("控制权限");
Role result = this.roleRepository.save(role);
System.out.println(result);
}
@Test
public void testDelete() {
this.roleRepository.delete(1);
}
}
测试结果省略...
四、整合 Mybatis
整合 MyBatis 有两种方式:
使用 mybatis 官方提供的 Spring Boot 整合包实现。
使用 mybatis-spring 整合的方式,也就是传统的方式(推荐,此方式容易控制 MyBatis 的配置)。
4.1 配置依赖
方式一:使用官方整合包
1)添加依赖:
<!-- springboot,mybatis 整合包 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!-- mysql 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2)配置数据库连接:
在 application.properties 中添加:
# 数据源配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=tiger
# mybatis 配置
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
方式二:原始 Jar 包 + 手动编程
1)添加依赖:
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<!-- spring,mybatis整合包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- mysql 驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
2)配置数据库连接:
在 application.properties 中添加:
# 数据源配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=tiger
3)创建配置类:
@Configuration
public class MyBatisConfiguration {
@Bean
@ConditionalOnMissingBean // 当容器里没有指定的 Bean 的情况下创建该对象
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 设置数据源
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置mybatis的主配置文件
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource("mybatis/mybatis-config.xml"));
// 设置mapper映射文件
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] mapperXml;
try {
mapperXml = resolver.getResources("classpath:mybatis/mapper/*.xml");
sqlSessionFactoryBean.setMapperLocations(mapperXml);
} catch (IOException e) {
e.printStackTrace();
}
// 设置别名包
sqlSessionFactoryBean.setTypeAliasesPackage("com.light.springboot.domain");
return sqlSessionFactoryBean;
}
@Bean
@ConditionalOnBean(SqlSessionFactoryBean.class) // 当 SqlSessionFactoryBean 实例存在时创建对象
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.light.springboot.mapper");
return mapperScannerConfigurer;
}
}
以上便是两种方式的配置的不同之处,不同之处就在于如何配置 mybatis 配置文件和 mapper 映射文件的路径。
在 src/main/resources 下创建 mybatis 文件夹,并在 mybatis 文件夹中创建 "mybatis-config.xml" 配置文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 获取数据库自增主键值 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 使用列别名替换列名,默认为 true -->
<setting name="useColumnLabel" value="true"/>
<!-- 开启驼峰命名转换:Table(create_time) => Entity(createTime) -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
mybatis 文件夹下再创建一个 "mapper" 文件夹,里边存放 Mpper 接口对应的 mapper 映射文件。
4.2 测试
4.2.1 建表
在 MySQL 中创建名为 springboot 的数据库,在该库中创建 role 表:
CREATE TABLE `department` (
`id` INT(11) NOT NULL,
`name` VARCHAR(10) NOT NULL,
`descr` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
4.2.2 实体类
public class Department implements Serializable{
private static final long serialVersionUID = 6067283535977178571L;
private Integer id;
private String name;
private String descr;
}
setet 和 getter 方法省略。
4.2.3 Mapper 接口
@Mapper
public interface DepartmentMapper {
public void insert(Department department);
public Department getById(Integer id);
public void update(Department department);
public void deleteById(Integer id);
}
mybatis/mapper/departmentMapper.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.light.springboot.dao.DepartmentMapper">
<insert id="insert" parameterType="com.light.springboot.domain.Department">
insert into department(id,name,descr) values(#{id},#{name},#{descr})
</insert>
<select id="getById" parameterType="java.lang.Integer" resultType="com.light.springboot.domain.Department">
select id,name,descr from department where id = #{id}
</select>
<update id="update" parameterType="com.light.springboot.domain.Department">
update department set descr = #{descr} where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Integer">
delete from department where id = #{id}
</delete>
</mapper>
4.2.4 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class DepartmentTest {
@Autowired
private DepartmentMapper departmentMapper;
@Test
public void testInsert() {
Department department = new Department();
department.setId(1);
department.setName("研发部");
department.setDescr("开发产品");
this.departmentMapper.insert(department);
}
@Test
public void testGetById() {
Department department = this.departmentMapper.getById(1);
System.out.println(department);
}
@Test
public void testUpdate() {
Department department = new Department();
department.setId(1);
department.setDescr("开发高级产品");
this.departmentMapper.update(department);
}
@Test
public void testDeleteById() {
this.departmentMapper.deleteById(1);
}
}
测试结果省略...
五、配置 Druid 数据源
同样地,有两种方式配置:
1)Spring boot,Druid 整合包
2)原始 jar 包 + 手动编程
5.1 Spring boot,Druid 整合包方式
5.1.1 添加依赖
<!-- springboot,druid 整合包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.8</version>
</dependency>
5.1.2 添加配置
在 application.properties 中添加:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=tiger
# 修改数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
spring.datasource.druid.pool-prepared-statements=true
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
spring.datasource.druid.filters=stat,wall,log4j
5.2 原始 jar 包 + 手动编程方式
5.2.1 添加依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
5.2.2 添加配置
spring.datasource.druid.driverClassName=com.mysql.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.druid.username=root
spring.datasource.druid.password=tiger
spring.datasource.druid.initialSize=5
spring.datasource.druid.minIdle=5
spring.datasource.druid.maxActive=20
spring.datasource.druid.maxWait=60000
spring.datasource.druid.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.min-evictableIdleTimeMillis=300000
spring.datasource.druid.validationQuery=SELECT 1 FROM DUAL
spring.datasource.druid.testWhileIdle=true
spring.datasource.druid.testOnBorrow=false
spring.datasource.druid.testOnReturn=false
spring.datasource.druid.poolPreparedStatements=true
spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.druid.filters=stat,wall
注意:配置中都是以 spring.datasource.druid 开头,使用驼峰命名
5.2.3 手动编程
@Configuration
public class DruidConfiguration {
@ConfigurationProperties(prefix = "spring.datasource.druid")
@Bean(initMethod = "init",destroyMethod = "close")
public DruidDataSource dataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setProxyFilters(Arrays.asList(statFilter()));
return ds;
}
@Bean
public Filter statFilter() {
StatFilter filter = new StatFilter();
filter.setSlowSqlMillis(5000);
filter.setLogSlowSql(true);
filter.setMergeSql(true);
return filter;
}
}
通过上文 MyBatis 的测试代码,运行结果如下:

项目已经使用了 Druid 数据源了。
六、配置 Druid 监控
默认情况下,Druid 的监控统计功能和页面是开启的。
我们启动项目,访问 http://localhost:8080/druid/index.html,如下图:

为了保证访问的安全性,我们可以如下配置:
在 application.properties 中添加:
## druid 监控
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
## druid 监控页面
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.login-username=druid
spring.datasource.druid.stat-view-servlet.login-password=druid123
重启项目,再次访问 http://localhost:8080/druid/index.html 地址时需要身份验证:

七、源码下载
八、参考资料
Spring Boot 入门之持久层篇(三)的更多相关文章
- spring boot整合双持久层框架jpa、mybatis
公司之前用的是spring boot + jpa,但由于jpa无法完美的解决某些动态查询问题,就使用的jdbcTemplate 动态封装SQL,由于代码相对复杂,可读性差,现准备再引入mybatis. ...
- Spring Boot 入门之基础构建篇(一)
博客地址:http://www.moonxy.com 一.前言 随着 Spring 的功能越来越强,在使用 Spring 的时候,门槛也变得高了起来,诸如搭建一个基于 Spring 的 Web 程序却 ...
- spring boot入门,看这篇文章就够了
一.SpringBoot入门 1.基本介绍 简化Spring应用开发的一个框架.整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 优点: 快速创建独立运行的Spring项目以及与主 ...
- Spring Boot 入门之整合 log4jdbc 篇(六)
博客地址:http://www.moonxy.com 一.前言 Spring Data JPA 默认采用 Hibernate 实现.Hibernate 的 showSql 配置只打印 SQL,但并不打 ...
- Spring Boot 入门之缓存和 NoSQL 篇(四)
原文地址:Spring Boot 入门之缓存和 NoSQL 篇(四) 博客地址:http://www.extlight.com 一.前言 当系统的访问量增大时,相应的数据库的性能就逐渐下降.但是,大多 ...
- Spring Boot 入门之单元测试篇(五)
博客地址:http://www.moonxy.com 一.前言 JUnit 是一个由 Java 语言编写的开源的回归测试(回归测试是指重复以前全部或部分的相同测试)框架,由Erich Gamma 和 ...
- Spring Boot入门教程1、使用Spring Boot构建第一个Web应用程序
一.前言 什么是Spring Boot?Spring Boot就是一个让你使用Spring构建应用时减少配置的一个框架.约定优于配置,一定程度上提高了开发效率.https://zhuanlan.zhi ...
- Spring Boot入门教程2-1、使用Spring Boot+MyBatis访问数据库(CURD)注解版
一.前言 什么是MyBatis?MyBatis是目前Java平台最为流行的ORM框架https://baike.baidu.com/item/MyBatis/2824918 本篇开发环境1.操作系统: ...
- Spring boot学习1 构建微服务:Spring boot 入门篇
Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...
随机推荐
- 无密码登陆的ssh和ssh-agent
原文地址:http://lxshopping.blog.51cto.com/4542643/1179864/ 一,不需要输密码的ssh 原理:首先服务器端把公钥传给Client端,Client端在验证 ...
- 十五、dbms_space(分析段增长和空间的需求)
1.概述 作用:用于分析段增长和空间的需求. 2.包的组成 1).unused_space作用:用于返回对象(表.索引.簇)的未用空间语法:dbms_space.unused_space(segmen ...
- nfs的简单搭建与原理
nfs最大的缺点是单点,只能一对一nfs统称存储服务器,放视频图片之类的东西,所以服务器的容量很大数字都是放在数据库里边的, nfs的挂载原理 客户端怎么知道服务端的开启端口? 找rpcbind,再启 ...
- C++复制控制:拷贝构造函数
一.拷贝构造函数是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用.与默认构造函数一样 ,拷贝构造函数可由编译器隐式调用.拷贝构造函数应用的场合为: (1)根据另一个同类 ...
- .net 枚举(Enum)使用总结
在实际问题中,有些变量的取值被限定在一个有限的范围内.例如,一个星期内只有七天,一年只有十二个月,性别只有男跟女等等.如果把这些量说明为整型.字符型或其它类型显然是不妥当的.为此,C#提供了一种称为“ ...
- vue.js 源代码学习笔记 ----- instance init
/* @flow */ import config from '../config' import { initProxy } from './proxy' import { initState } ...
- java高并发下的数据安全
高并发下的数据安全 我们知道在多线程写入同一个文件的时候,会存现“线程安全”的问题(多个线程同时运行同一段代码,如果每次运行结果和单线程运行的结果是一样的,结果和预期相同,就是线程安全的).如果是My ...
- (转)MapReduce Design Patterns(chapter 2 (part 2))(三)
Median and standard deviation 中值和标准差的计算比前面的例子复杂一点.因为这种运算是非关联的,它们不是那么容易的能从combiner中获益.中值是将数据集一分为两等份的数 ...
- React-Native进阶_6.导航 Naviagtion传递数据并展示
接着上面 Navigation 继续学习传递数据给下一个页面 onPress={() => this.props.navigation.navigate('Detail',{info:movie ...
- Kotlin都转正成Android官方语言了,你还不试一下?
想想Android Studio 和Eclipse ,我觉得你还是有必要入手Kotlin了. 站好队很重要. 以前的一篇总体概括老文,大家可以看看~ 爽翻天!告别Java.一起来使用kotlin开发完 ...