SpringBoot系列(17):基于Spring内置的JdbcTemplate实现极简CRUD功能

作者: 修罗debug
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。


摘要:现如今市面上以Java技术栈为主、用于开发Web项目的主流持久层框架主要包括Hibernate、JPA、Spring Data JPA、ibatis、Mybatis等等,其中,用的比较多的当属Mybatis、Hibernate/ Spring Data JPA,即所谓的SSM或者SSH项目啦!本文我们将基于Spring内置的JdbcTemplate实现一个功能模块的CRUD操作。

内容:对于目前市面上流行的持久层框架Mybatis、Hibernate/ Spring Data JPA,相信大家或多或少都见过,甚至有的小伙伴都已经用它们来撸过N套项目了,本文我们就不分享介绍这些主流框架的应用了。相反,我们回归到核心框架Spring中内置JdbcTemplate组件,一起来体验一下Spring 内置的JdbcTemplate如何实现一个业务模块的CRUD操作功能。

JdbcTemplate,顾名思义,其实是从传统的JDBC操作组件演进而来的,但是它却不能等同于传统的JDBC(否则,就没有介绍的必要了),它屏蔽了传统JDBC的数据库连接操作、语句管理以及资源关闭管理等既繁琐、而又重复性的操作代码,采用“模板设计模式”,并基于强大的Spring框架作为依托而隆重推出的操作数据库的利器!

在对业务模块进行CRUD等功能操作之前,我们需要在我们的项目中显示、自动注入JdbcTempalte操作组件(当然啦,你如果喜欢用XML进行配置,那也完全是ok的)!

    @Bean("primaryJdbcTemplate")
public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource){
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
return jdbcTemplate;
}

在这里,我们需要注入主数据源primaryDataSource实例,用来构造JdbcTemplate实例。之后我们以数据库表user为案例,分享介绍极简的CRUD功能,其中,该数据库表user的DDL定义如下所示:  

CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '名字',
`code` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '工号',
`email` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';

(1)首先,我们自然需要创建一个Controller,用于接收前端过来的请求数据,这个controller下自然由CRUD几个方法,其完整的源代码如下所示:  

/**
* spring jdbcTemplate
* @Author:debug (SteadyJack)
* @Link: weixin-> debug0868 qq-> 1948831260
* @Date: 2019/11/11 21:33
**/
@RestController
@RequestMapping("jdbc/template/user")
public class JbdcTemplateController extends AbstractController{

@Autowired
private JdbcTemplateService jdbcTemplateService;

//TODO:新增
@RequestMapping(value = "add",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public BaseResponse info(@RequestBody @Validated UserDto userDto, BindingResult result){
String checkRes=ValidatorUtil.checkResult(result);
if (StringUtils.isNotBlank(checkRes)){
return new BaseResponse(StatusCode.InvalidParams.getCode(),checkRes);
}
BaseResponse response=new BaseResponse(StatusCode.Success);
try {
int res=jdbcTemplateService.addUser(userDto);
response.setData(res);

}catch (Exception e){
response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
}
return response;
}

//TODO:查询一个
@RequestMapping(value = "query/one",method = RequestMethod.GET)
public BaseResponse queryOne(@RequestParam Integer id){
if (id<=0){
return new BaseResponse(StatusCode.InvalidParams);
}
BaseResponse response=new BaseResponse(StatusCode.Success);
try {
response.setData(jdbcTemplateService.queryUserById(id));

}catch (Exception e){
response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
}
return response;
}

//TODO:查询列表
@RequestMapping(value = "query/list",method = RequestMethod.GET)
public BaseResponse queryList(@RequestParam String search){
BaseResponse response=new BaseResponse(StatusCode.Success);
Map<String,Object> resMap= Maps.newHashMap();
try {
resMap.put("数据列表-v1",jdbcTemplateService.queryListV1(search));
resMap.put("数据列表-v2",jdbcTemplateService.queryListV2(search));

}catch (Exception e){
response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
}
response.setData(resMap);
return response;
}

//TODO:删除
@RequestMapping(value = "delete",method = RequestMethod.POST)
public BaseResponse delete(@RequestParam Integer id){
if (id<=0){
return new BaseResponse(StatusCode.InvalidParams);
}
BaseResponse response=new BaseResponse(StatusCode.Success);
try {
response.setData(jdbcTemplateService.delete(id));

}catch (Exception e){
response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
}
return response;
}
}

其中的UserDto的源码如下所示:  

@Data
public class UserDto implements Serializable{

@NotBlank(message = "name不能为空!")
private String name;

@NotBlank(message = "code不能为空!")
private String code;

@NotBlank(message = "email不能为空!")
private String email;
}

(2)最后,自然是贴出其Service的具体实现逻辑啦:  

/**
* Spring+JdbcTemplate实战
* @Author:debug (SteadyJack)
* @Link: weixin-> debug0868 qq-> 1948831260
* @Date: 2019/11/11 21:34
**/
@Service
public class JdbcTemplateService {

private static final Logger log= LoggerFactory.getLogger(JdbcTemplateService.class);

private static final String insertSql="insert into user (name, code, email) values (?,?,?)";

private static final String queryOneSql="SELECT id,`name`,`code`,email FROM `user` WHERE id=?";

private static final String queryListSql="SELECT id,`name`,`code`,email FROM `user` WHERE 1=1 AND (name LIKE ? OR `code` LIKE ? OR email LIKE ?)";

private static final String deleteSql="DELETE FROM `user` WHERE id=?";


@Resource(name = "primaryJdbcTemplate")
private JdbcTemplate primaryJdbcTemplate;

//TODO:新增
public int addUser(UserDto dto) throws Exception{
return primaryJdbcTemplate.update(insertSql, ps -> {
ps.setString(1,dto.getName());
ps.setString(2,dto.getCode());
ps.setString(3,dto.getEmail());
});
}

//TODO:查询-一个 - 结果集与实体对象映射
public User queryUserById(final Integer id){
try {
return primaryJdbcTemplate.queryForObject(queryOneSql, new Object[]{id}, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
User entity=new User();
entity.setId(rs.getInt("id"));
entity.setName(rs.getString("name"));
entity.setCode(rs.getString("code"));
entity.setEmail(rs.getString("email"));
return entity;
}
});
}catch (Exception e){
log.error("spring-jdbcTemplate-查询用户信息发生异常:id={}",id,e.fillInStackTrace());
}
return null;
}

//TODO:列表查询一
public List<User> queryListV1(final String search) throws Exception{
return primaryJdbcTemplate.query(queryListSql, new Object[]{"%" + search + "%","%" + search + "%","%" + search + "%"}, new RowMapper<User>() {
User entity;
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
entity=new User();
entity.setId(rs.getInt("id"));
entity.setName(rs.getString("name"));
entity.setCode(rs.getString("code"));
entity.setEmail(rs.getString("email"));
return entity;
}
});
}

//TODO:列表查询二
public List<User> queryListV2(final String search) throws Exception{
return primaryJdbcTemplate.query(queryListSql,
new Object[]{"%" + search + "%","%" + search + "%","%" + search + "%"}, new BeanPropertyRowMapper<>(User.class));
}

//TODO:删除 – 物理删除
public int delete(final Integer id){
return primaryJdbcTemplate.update(deleteSql,id);
}
}

其中的“列表实体查询”操作,我们提供了两种不同的API来实现。将项目跑起来,然后打开postman对相应的请求接口执行一波骚操作,体验体验Spring内置的JdbcTemplate的魅力:

A.“新增/修改操作”的操作效果图:


B.“查询单一实体信息”的操作效果图:


C.“查询列表实体信息”的操作效果图:


D.“删除实体信息”的操作效果图:


好了,本篇文章我们就介绍到这里了,其他相关的技术,感兴趣的小伙伴可以关注底部Debug的技术公众号,或者加Debug的微信,拉你进“微信版”的真正技术交流群!一起学习、共同成长!


补充:

1、本文涉及到的相关的源代码可以到此地址,check出来进行查看学习:

https://gitee.com/steadyjack/SpringBootTechnology

2、最近Debug发布了几门重量级的课程,感兴趣的小伙伴可以前往观看学习:
(1) 缓存中间件Redis技术入门与应用场景实战(SpringBoot2.x + 抢红包系统设计与实战) 
https://www.fightjava.com/web/index/course/detail/12

(2)  企业权限管理平台(SpringBoot2.0+Shiro+Vue+Mybatis) 
https://www.fightjava.com/web/index/course/detail/8

3、关注一下Debug的技术微信公众号,最新的技术文章、课程以及技术专栏将会第一时间在公众号发布哦!