Spring学习之旅(十一)--JDBC

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 以上的支持。

原文地址:https://www.cnblogs.com/markLogZhu/p/11400489.html