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. Spring还可以这样用缓存,你知道吗?

    大家在项目开发过程中,或多或少都用过缓存,为了减少数据库的压力,把数据放在缓存当中,当访问的请求过来时,直接从缓存读取.缓存一般都是基于内存的,读取速度比较快,市面上比较常见的缓存有:memcache ...

  2. linux初学者-输出输入管理

      1.输出重定向 在linux中,因为用户的权限不同,所以访问某些文件或者目录会被拒绝而形成错误输出,这些错误的输出也会显示出来.一般正确输出的编号为1,错误输出的编号为2.如下图,在普通用户stu ...

  3. 100天搞定机器学习|Day8 逻辑回归的数学原理

    机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机器学习|D ...

  4. 01 | 健康之路 kubernetes(k8s) 实践之路 : 开篇及概况

    近几年容器相关的技术大行其道,容器.docker.k8s.mesos.service mesh.serverless等名词相信大家多少都有听过,国内互联网公司无一不接触和使用相关技术. 健康之路早在2 ...

  5. MYSQL 时间轴数据 获取同一天数据的前3条

    创建表数据 CREATE TABLE `praise_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', `pic_id` va ...

  6. input属性设置type="number"之后, 仍可输入e, E, -, + 的解决办法

    <el-input v-model="scope.row.variables.leaderbuweiscores.score" @keyup.native="cha ...

  7. Thread.Sleep太久,界面卡死

    在Winform程序的UI界面使用Thread.Sleep,窗体界面会被卡死,如图1所示,程序sleep 5000毫秒,时间到了之后,按钮的名称才更改过来,窗体也能被鼠标拖动.而用Delay方法,就能 ...

  8. 夯实Java基础(十)——抽象类和接口

    转载自:http://cmsblogs.com/ 该博主的网站上干货非常!非常!非常多(说三遍),强烈推荐大家前去学习. 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法 抽象类与接口是 ...

  9. oracle 正确删除归档日志,并清除 V$ARCHIVED_LOG 数据

    1. 连接 RMAN 管理 rman target / 2. 查看归档日志列表 RMAN> crosscheck archivelog all; 3. 删除所有归档日志 RMAN> DEL ...

  10. Kafka集群模式安装(二)

    我们来安装Kafka的集群模式,三台机器: 192.168.131.128 192.168.131.130 192.168.131.131 Kafka集群需要依赖zookeeper,所以需要先安装好z ...