JDBC 是数据持久化的一种比较常见的方案,Spring 也对它进行了支持。

在开始 JDBC 的使用之前,我们要先做下一些准备工作。

配置数据源

Spring 上下文中可以数据源 Bean 有如下多种方式:

  • 通过 JDBC 驱动程序定义的数据源;
  • 通过 JNDI 查找的数据源;
  • 连接池的数据源

我们通常使用 连接池 的方式来配置,这里也只讲解这种方案,其他两种可以自行摸索。

Spirng 并没有直接提供数据源连接池实现,但是有多种开源的实现,如:

我们这里采用阿里的 druid 连接池。

引入依赖

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.20.RELEASE</version>
</dependency> <!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!-- mysql连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>

配置连接池对象

@Configuration
public class DataBaseConfig { @Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
// 设置驱动
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
// 设置连接 URL
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/learn?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true");
// 设置连接账号
dataSource.setUsername("root");
// 设置连接密码
dataSource.setPassword("sa000");
// 设置连接池初始连接数量
dataSource.setInitialSize(5);
// 设置连接池最大连接数量
dataSource.setMaxActive(10);
return dataSource;
}
}

初始化数据库

-- 创建数据库
DROP DATABASE IF EXISTS learn;
CREATE DATABASE IF NOT EXISTS learn DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
-- 选择数据库
USE sugar; SET FOREIGN_KEY_CHECKS=0;
-- 创建用户表
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`account` varchar(45) DEFAULT NULL COMMENT '账号',
`password` varchar(45) DEFAULT NULL COMMENT '密码',
`salt` varchar(45) DEFAULT NULL COMMENT 'md5密码盐',
`name` varchar(45) DEFAULT NULL COMMENT '名字',
`birthday` datetime DEFAULT NULL COMMENT '生日',
`sex` int(11) DEFAULT NULL COMMENT '性别(1:男 2:女)',
`email` varchar(45) DEFAULT NULL COMMENT '电子邮件',
`phone` varchar(45) DEFAULT NULL COMMENT '电话',
`role_id` varchar(255) DEFAULT NULL COMMENT '角色id',
`dept_id` int(11) DEFAULT NULL COMMENT '部门id',
`status` int(11) DEFAULT NULL COMMENT '状态(1:启用 2:冻结 3:删除)',
`createtime` datetime DEFAULT NULL COMMENT '创建时间',
`version` int(11) DEFAULT NULL COMMENT '保留字段',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8 COMMENT='管理员表'; -- 插入
INSERT INTO `sys_user` VALUES ('1', 'girl.gif', 'admin', '871e11b8f4ce630ef302a79265fd4887', '8pgby', 'admin', '2018-05-05 00:00:00', '2', 'sn93@qq.com', '18200000000', '1', '27', '1', '2018-01-29 08:49:53', '25'); SET FOREIGN_KEY_CHECKS = 1;

实体对象

public class User {

    private Long id;

    private String avatar;

    private String account;

    private String password;

    private String salt;

    private String name;

    private String birthday;

    private Integer sex;

    private String email;

    private String phone;

    private String roleId;

    private Long deptId;

    private Integer status;

    private Date createtime;

    private Long version;

	// get/set......
}

原始 JDBC

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RootConfig.class)
public class DaoTest { @Autowired
private DataSource dataSource; @Test
public void testJDBC() {
String sql = "select id,account from sys_user where id = ? ";
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareCall(sql);
statement.setLong(1, 1);
resultSet = statement.executeQuery();
if (resultSet.next()) {
Long id = resultSet.getLong("id");
String account = resultSet.getString("account");
Assert.assertEquals(new Long(1), id);
Assert.assertEquals("admin", account);
}
} catch (SQLException e) {
System.out.println("异常:"+ e.getMessage());
} finally {
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement !=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection !=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} } }

可以看到大部分的代码都是用来进行 资源管理异常处理,实际的业务逻辑就只有几行。

JDBC 模板

Spring 为我们提供了 JDBC 模板 ,由它来进行资源管理和异常处理的工作,从而简化了 JDBC 代码。Spring 提供了三种模板类供我们选择:

  • JdbcTemplate: 最基本的 Spring JDBC 模板,这个模板支持简单的 JDBC 数据库访问功能以及基于索引参数的查询。
  • NamedParameterJdbcTemplate: 使用该模板类执行查询时可以将值以命名参数的形式绑定到 SQL 中,而不是使用简单的索引参数
  • SimpleJdbcTemplate: 该模板类利用 Java5 的一些特性如自动装箱、泛型以及可变参数来简化 JDBC 模板的使用

Spirng 3.1 开始 SimpleJdbcTemplate 已经被废弃了,其 Java 5 的特性被转移到了 JdbcTemplate 中。所以大多数情况我们直接使用 JdbcTemplate 即可。

配置 JDBC 模板对象

@Configuration
public class DataBaseConfig { ...... @Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}

单元测试

@Autowired
private JdbcTemplate jdbcTemplate; @Test
public void testJdbcTemplate() {
String sql = "select id,account,birthday from sys_user where id = ?";
User user = jdbcTemplate.queryForObject(sql, new UserRowMapper(),1);
Assert.assertEquals(new Long(1), user.getId());
Assert.assertEquals("admin", user.getAccount());
} private static final class UserRowMapper implements RowMa pper<User>{ @Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setId(resultSet.getLong("id"));
user.setAccount(resultSet.getString("account"));
return user;
}
}

可以看到使用模板后代码量大幅度减少,只有业务代码存在了。

除了使用 RowMapper 外,也可以直接用 Lambda 表达式:

@Test
public void testJdbcTemplate2() {
String sql = "select id,account,birthday from sys_user where id = ?";
User user = jdbcTemplate.queryForObject(sql, (resultSet,i)->{
User u = new User();
u.setId(resultSet.getLong("id"));
u.setAccount(resultSet.getString("account"));
return u;
},1);
Assert.assertEquals(new Long(1), user.getId());
Assert.assertEquals("admin", user.getAccount());
}

Lambda 表达式比起申明一个 RowMapper 对象来更直观,但是需要 JDK 8 以上的支持。

Spring学习之旅(十一)--JDBC的更多相关文章

  1. Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探

    由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...

  2. Spring学习之旅(十)--MockMvc

    在之前的 Spring学习之旅(八)--SpringMVC请求参数 我们是通过在控制台输出来验证参数是否正确,但是这样做实在是太耗时间了,我们今天来学习下 MockMvc,它可以让我们不需要启动项目就 ...

  3. Spring学习之旅(六)--SpringMVC集成

    对大多数 Java 开发来说,基于 web 的应用程序是我们主要的关注点. Spring 也提供了对于 web 的支持,基于 MVC 模式的 Spring MVC 能够帮助我们灵活和松耦合的完成 we ...

  4. Spring学习记录(十四)---JDBC基本操作

    先看一些定义: 在Spring JDBC模块中,所有的类可以被分到四个单独的包:1.core即核心包,它包含了JDBC的核心功能.此包内有很多重要的类,包括:JdbcTemplate类.SimpleJ ...

  5. Spring学习之旅(十五)--SpringBoot

    在使用 Spring 的过程中,有时候会出现一些 ClassNotFoundException 异常,这是因为 JAR 依赖之间的版本不匹配所导致的.而 Spring Boot 就能避免绝大多数依赖版 ...

  6. Spring学习之旅(十三)--使用NoSQL数据库

    除了关系型数据库之外,现在还有一种 NoSQL 数据库非常流行,而 Spring 自然也没有放过对它的支持. NoSQL 数据库有很多种,如: MongoDBGenericJackson2JsonRe ...

  7. Spring学习之旅(十二)--持久化框架

    对于本职工作来说 JDBC 就可以很好的完成,但是当我们对持久化的需求变得更复杂时,如: 延迟加载 预先抓取 级联 JDBC 就不能满足了,我们需要使用 ORM框架 来实现这些需求. Spring 对 ...

  8. Spring学习之旅(三)--装配Bean

    装配 Bean 的方式 在 XML 中进行显式配置 在 Java 中进行显式配置 隐式的 Bean 发现机制和自动装配 Spring 提供了以上三种方式进行 Bean 的配置,可以根据自己的需求选择一 ...

  9. Spring学习之旅(一)--初始Spring

    之前从博客.视频断断续续的学到了 Spring 的相关知识,但是都是一个个碎片化的知识.刚好最近在读 <Sprign实战(第四版)>,所以借此机会重新整理下Spring 系列的内容. Sp ...

随机推荐

  1. [leetcode]95 Unique Binary Search Trees II (Medium)

    原题 字母题添加链接描述 一开始完全没有思路.. 百度看了别人的思路,对于这种递归构造的题目还是不熟,得多做做了. 这个题目难在构造出来.一般构造树都需要递归. 从1–n中任意选择一个数当做根节点,所 ...

  2. vuex的实现

    源代码可以查看我的github:  https://github.com/Jasonwang911/TryHardEveryDay/tree/master/Vuex/vuex-resouce  欢迎s ...

  3. Appium自动化测试环境搭建

    前言 Appium是一个开源的自动化测试框架,支持跨平台,支持多种编程语言,可用于原生,混合和移动web应用程序,使用webdriver驱动ios,android应用程序.那么为了学习app自动化测试 ...

  4. ld: warning: directory not found for option ''

    iOS开发中经常遇到这样的警告,如图所示: 原因是存在未用到的目录. 解决方法:选择Build Settings,找到Search Paths中的Library Search Paths,如下图 删除 ...

  5. Java秒杀系统实战系列~商品秒杀代码实战

    摘要: 本篇博文是“Java秒杀系统实战系列文章”的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即“商品秒杀”功能模块的代码实战. 内容: “商品秒杀”功能模块是建立在“商品详情”功 ...

  6. HashMap、Hash Table、ConcurrentHashMap

    这个这个...本王最近由于开始找实习工作了,所以就在牛客网上刷一些公司的面试题,大多都是一些java,前端HTML,js,jquery,以及一些好久没有碰的算法题,说实话,有点难受,其实在我不知道的很 ...

  7. 【故障公告】发布 .NET Core 版博客站点引起大量 500 错误

    非常抱歉,今天上午的博客站点故障给大家带来了很大的麻烦,请大家谅解.这次故障是我们发布 .NET Core 版博客站点引起的,虽然我们进行了充分的准备,但还是低估了高并发下的复杂问题. 以下是故障背景 ...

  8. POI导入excel

    前言 在做后台管理的时候经常会用到excel导入的问题,就是将excel中的内容批量导入到数据库中,正好在新项目中我也做了excel导入的功能,来分享给大家,也给自己做个记录. 核心思想 excel导 ...

  9. 湫湫系列故事——设计风景线 HDU - 4514

    题目链接:https://vjudge.net/problem/HDU-4514 题意:判断没有没有环,如果没有环,通俗的讲就是找出一条最长的路,相当于一笔画能画多长. 思路:dfs判环. 最后就是没 ...

  10. RGW 学习 前言

    对于CEPH的学习已经有一段的时间了,最近的一段时间都是集中在RGW网关这一方面,所以准备将学习的过程以及源代码的分析,将以随笔的形式记录下来. 每天更新一章.