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. hdu6395 Sequence(分段矩阵快速幂)

    Sequence 题目传送门 解题思路 可以比较容易的推出矩阵方程,但是由于p/i向下取整的值在变,所以要根据p/i的变化将矩阵分段快速幂.p/i一共有sqrt(p)种结果,所以最多可以分为sqrt( ...

  2. JavaSE总结(一)

    一.Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年 ...

  3. Java类方法重载与重写

    目录 - 方法重载 - 方法重写 @(Java类方法重载与重写) - 方法重载 1.方法名相同 2.参数列表不同 public void person(double height,double wei ...

  4. Java类什么情况下被初始化?

    1.创建类的实例(new 的方式).访问某个类或接口的静态变量,或者对该静态变量赋值,调用类的静态方法 2.反射的方式 3.当初始化一个类的时候,如果发现其父类还没有进行初始化,则需先触发其父类的初始 ...

  5. [算法]LeetCode 1.两数之和

    LeetCode 1.两数之和(python) 1.朴素解法 最朴素的两个for循环大法: class Solution: def twoSum(self, nums: List[int], targ ...

  6. mybatis动态插入数据库

    <insert id="dynamicAddUser"> insert into t_user <!-- trim 对所有的表中列名 进行动态处理 --> ...

  7. 【MySQL】Unknown column 'column_name' in 'field list'

    使用 INSERT INTO - SELECT FROM - ON DUPLICATE KEY UPDATE 时遇到了这个问题,百思不得其解

  8. 隐马尔科夫模型HMM介绍

    马尔科夫链是描述状态转换的随机过程,该过程具备“无记忆”的性质:即当前时刻$t$的状态$s_t$的概率分布只由前一时刻$t-1$的状态$s_{t-1}$决定,与时间序列中$t-1$时刻之前的状态无关. ...

  9. dubbo异常处理

    dubbo异常处理 我们的项目使用了dubbo进行不同系统之间的调用. 每个项目都有一个全局的异常处理,对于业务异常,我们会抛出自定义的业务异常(继承RuntimeException). 全局的异常处 ...

  10. 一个项目的SpringCloud微服务改造过程

    SSO是公司一个已经存在了若干年的项目,后端采用SpringMVC.MyBatis,数据库使用MySQL,前端展示使用Freemark.今年,我们对该项目进行了一次革命性的改进,改造成SpringCl ...