`

Spring基础:数据访问(1)

阅读更多
Spring JDBC通过模板和回调机制大大降低了使用JDBC的难度,以一种更直接,更间接的方式使API用户不用去关心资源获取,Statement创建,异常处理,资源释放等繁杂而乏味的工作,只需要去做那些必不可少的事。

以下例子都是基于Derby数据库的,这个数据库是JDK自带的,无需另外安装。

1.Spring-Jdbc初步
在Maven Project中使用JdbcTemplate的话,除了在POM的依赖中加上JDBC Driver,还要使用DataSource,有很多开源的数据库连接池,比如Commons-Pool,C3P0,我们在第一步中使用了Spring自带的DriverManagerDataSource。
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.apache.derby.jdbc.ClientDriver");
ds.setUrl("jdbc:derby://localhost:1527/sampledb_jdbc;create=true");

JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(ds);

String sql = "create table t_user("
        + "user_id int generated by default as identity"
        + ",user_name varchar(60)"
        + ",constraint PK_T_USER primary key(user_id))";
jdbcTemplate.execute(sql);

****需要特别注意的是,在Derby中以编程的方式建立的数据库,默认是在APP这个Schema下面的

2.Spring风格的JDBC
我们来配置一个Spring风格的Dao类
首先我们来写一个Respository类
@Repository
public class ForumDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public void initDb() {
        String sql = "create table t_user("
                + "user_id int generated by default as identity"
                + ",user_name varchar(60)"
                + ",constraint PK_T_USER primary key(user_id))";
        jdbcTemplate.execute(sql);
    }
}

注意,需要使用@Repository自动注入
然后我们在xml中进行配置
<context:property-placeholder location="classpath:jdbc.properties"/>
<context:component-scan base-package="com.firethewhole.maventest09.dao"/>

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"/>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>

这里我们使用类${}的占位符,所以还需要额外配置一个属性文件
jdbc.driverClassName=org.apache.derby.jdbc.ClientDriver
jdbc.url=jdbc:derby://localhost:1527/sampledb_jdbc;create=true

我们来写一段代码测试一下吧
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ForumDaoTest {
    @Autowired
    private ForumDao forumDao;
    @Test
    public void testInitDb() {
        forumDao.initDb();
    }
}

然后打开derby控制台,发现已经这张t_user表已经被成功创建了。

3.基本的数据库操作
3.1 更改数据
public void addForum(Forum forum) {
        String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
        jdbcTemplate.update(sql, forum.getForumName(), forum.getForumDesc());
    }

更新或者新增都是用update方法,这个时候PreparedStatement会根据参数类型猜测对应的数据库字段类型,当然我们也可以指定数据库字段类型。
public void addForum(Forum forum) {
        final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
        Object[] params = new Object[] { forum.getForumName(), forum.getForumDesc() };
        jdbcTemplate.update(sql, params, new int[] { Types.VARCHAR, Types.VARCHAR });
    }

我们还可以使用PreparedStatementSetter回调方法
public void addForum(final Forum forum) {
        String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
        jdbcTemplate.update(sql, new PreparedStatementSetter() {
            public void setValues(PreparedStatement ps) throws SQLException {
                // 这里需要forum为final
                ps.setString(1, forum.getForumName());
                ps.setString(2, forum.getForumDesc());
            }
        });
    }

注意,这里的参数是final修饰符
还有一种PreparedStatementCreator回调方法,可以手工创建PreparedStatement对象
public void addForum(final Forum forum) {
        final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
        jdbcTemplate.update(new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                // 这里需要sql为final
                PreparedStatement ps = con.prepareStatement(sql);
                ps.setString(1, forum.getForumName());
                ps.setString(2, forum.getForumDesc());
                return ps;
            }
        });
    }

当然,我们在写入操作的时候,如果需要取得子增长主键的值,该怎么做呢?
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.apache.derby.jdbc.ClientDriver");
ds.setUrl("jdbc:derby://localhost:1527/sampledb_jdbc");
final String sql = "insert into t_user1(user_name) values(?)";

JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(ds);

KeyHolder keyHolder = new GeneratedKeyHolder();

jdbcTemplate.update(new PreparedStatementCreator() {
	public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
		PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
		ps.setString(1, "admin");
		return ps;
	}
}, keyHolder);
if (keyHolder.getKey() != null)
	System.out.println(keyHolder.getKey().intValue());

注意,一定要在创建PreparedStatement的时候加上Statement.RETURN_GENERATED_KEYS,否则即使加上KeyHolder也是不会获得子增长列的
复合主键的情况,可以使用getKeys,如果是新增多条记录,返回了多个主键,则需要使用getKeyList方法。

3.2 批量更新数据
批量更新数据更加效率,也更加的节省数据库资源
public void addForums(final List<Forum> forums) {
    final String sql = "INSERT INTO t_forum(forum_name,forum_desc) VALUES(?,?)";
    jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
        public void setValues(PreparedStatement ps, int i) throws SQLException {
            Forum forum = forums.get(i);
            ps.setString(1, forum.getForumName());
            ps.setString(2, forum.getForumDesc());
        }
        public int getBatchSize() {
            return forums.size();
        }
    });
}

注意:getBatchSize方法是整个集合的元素个数,而不是每一批次的元素个数

3.3 查询
查询单条元素
public Forum getForum(final int forumId) {
    String sql = "SELECT forum_name,forum_desc FROM t_forum WHERE forum_id=?";
    final Forum forum = new Forum();
    jdbcTemplate.query(sql, new Object[] { forumId }, new RowCallbackHandler() {
        public void processRow(ResultSet rs) throws SQLException {
            forum.setForumName(rs.getString("forum_name"));
            forum.setForumDesc(rs.getString("forum_desc"));
            forum.setForumId(forumId);
        }
    });
    return forum;
}

查询多条数据,使用List集合保存
public List<Forum> getForums(final int forumId, final int told) {
    String sql = "SELECT forum_id,forum_name,forum_desc FROM t_forum WHERE forum_id BETWEEN ? AND ?";
    final List<Forum> forums = new ArrayList<Forum>();
    jdbcTemplate.query(sql, new Object[] { forumId, told }, new RowCallbackHandler() {
        public void processRow(ResultSet rs) throws SQLException {
            Forum forum = new Forum();
            forum.setForumId(rs.getInt("forum_id"));
            forum.setForumName(rs.getString("forum_name"));
            forum.setForumDesc(rs.getString("forum_desc"));
            forums.add(forum);
        }
    });
    return forums;
}

另外,查询多条数据还可以使用RowMapper<T>来进行
public List<Forum> getForumsRowMapper(final int forumId, final int told) {
    String sql = "SELECT forum_id,forum_name,forum_desc FROM t_forum WHERE forum_id BETWEEN ? AND ?";
    return jdbcTemplate.query(sql, new Object[] { forumId, told }, new RowMapper<Forum>() {
        public Forum mapRow(ResultSet rs, int rowNum) throws SQLException {
            Forum forum = new Forum();
            forum.setForumId(rs.getInt("forum_id"));
            forum.setForumName(rs.getString("forum_name"));
            forum.setForumDesc(rs.getString("forum_desc"));
            return forum;
        }
    });
}

RowMapper<T>和RowCallbackHandler相比,RowMapper是将集合整个返回,所以如果查询结果很大的话会很占内存。RowCallbackHandler可以一条条结果处理。
查询单值
public int getForumNum() {
    String sql = "SELECT COUNT(*) FROM t_forum";
    return jdbcTemplate.queryForInt(sql);
}

还有queryForXXX等一整套函数,主要是用来返回单值结果。
分享到:
评论

相关推荐

    Spring基础:数据访问(3)

    NULL 博文链接:https://foreversky12.iteye.com/blog/2353141

    Spring基础:数据访问(2)

    NULL 博文链接:https://foreversky12.iteye.com/blog/2348313

    spring基础进阶技巧200篇.zip

    数据访问:介绍了Spring框架对数据库访问的支持,包括JDBC、ORM框架、事务管理等。 测试和调试:介绍了如何使用Spring进行单元测试和集成测试,以及调试技巧和工具的使用。 这本资源适合已经具备一定Spring基础知识...

    Spring面试专题.md

    * Spring DAO:对JDBC的抽象,简化了数据访问异常的处理; * Spring ORM:对现有的ORM框架的支持; * Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传; * Spring MVC:提供面向Web应用的Model-View-...

    SingleJDBCBase 基于Spring Framework基础上搭建的一个Java基础开发套件

    SingleJDBCBase 是基于Spring Framework基础上搭建的一个Java基础开发套件,以Spring MVC为模型视图控制器,JDBC为数据访问层。 * 核心框架:Spring Framework 4.2.7 * 安全框架: * 视图框架:Spring MVC 4.2.7 * ...

    Spring框架:深入解析、心得分享与实战应用

    同时,Spring还提供了强大的事务管理、数据访问、Web开发等功能,帮助开发者快速构建出高效、稳定的应用程序。 除了核心功能外,Spring框架还具有良好的扩展性,可以与其他技术栈轻松集成。无论是与数据库、消息...

    Spring Boot 实战开发2022年

    │ 开篇词 从零开始:为什么要学习 Spring Boot?.mp4 │ 01 家族生态:如何正确理解 ...│ 23 数据测试:如何使用 Spring 测试数据访问层组件?.mp4 │ 24 服务测试:如何使用 Spring 测试 Web 服务层组件?.mp4

    SingleMyBatis 是基于Spring Framework基础上搭建的一个Java基础开发套件

    SingleMyBatis 是基于Spring Framework基础上搭建的一个Java基础开发套件,以Spring MVC为模型视图控制器,MyBatis为数据访问层。 * 核心框架:Spring Framework 4.2.7 * 安全框架: * 视图框架:Spring MVC 4.2.7 *...

    SingleHibernate 是基于Spring Framework基础上搭建的一个Java基础开发套件

    SingleHibernate 是基于Spring Framework基础上搭建的一个Java基础开发套件,以Spring MVC为模型视图控制器,Hibernate为数据访问层。 * 核心框架:Spring Framework 4.2.7 * 安全框架: * 视图框架:Spring MVC ...

    SpringBatch+Spring+Mybatis+MySql (spring batch 使用jar)

    Spring Batch以POJO和大家熟知的Spring框架为基础,使开发者更容易的访问和利用企业级服务。Spring Batch可以提供大量的,可重复的数据处理功能,包括日志记录/跟踪,事务管理,作业处理统计工作重新启动、跳过,和...

    Spring Boot 技术栈学习分享,涵盖了基础知识、Web开发、数据访问-spring-boot-route.zip

    Spring Boot 技术栈学习分享,涵盖了基础知识、Web开发、数据访问-spring-boot-route

    spring4.3.9相关jar包

    spring-jdbc.jar(必须) :这个jar 文件包含对Spring 对JDBC 数据访问进行封装的所有类。 外部依赖spring-beans,spring-dao。 spring-web.jar(必须) :这个jar 文件包含Web 应用开发时,用到Spring 框架时所需...

    SpringData.zip

    Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。Spring Data 包含多个子项目:Commons - 提供...

    SpringBoot使用Spring-data-jpa简化数据访问层

    虽然一些基础的数据访问已经可以得到很好的复用,但是在代码结构上针对每个实体都会有一堆Dao的接口和实现。 由于模板Dao的实现,使得这些具体实体的Dao层已经变的非常“薄”,有一些具体实体的Dao实现可能完全就是...

    Spring Data实战

    Spring Data项目就是一种简化Java应用构建的数据访问技术,它可以帮助开发人员高效地使用最新的数据处理和管理工具,同时还能够以最新的方式使用传统的数据库。  《Spring Data实战》从Spring Data背景知识、关系型...

    Spring MVC 3.0实战指南.ppt

    1、Spring MVC框架简介 2、HTTP请求地址映射 3、HTTP请求数据的绑定 4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7、其它 目录: Spring MVC 3.0新特性 Spring MVC框架结构 Spring MVC框架结构 框架...

    Spring3MVC注解教程.ppt

    1、Spring MVC框架简介 2、HTTP请求地址映射 3、HTTP请求数据的绑定 4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7、其它 目录: Spring MVC 3.0新特性 Spring MVC框架结构 Spring MVC...

    《JAVA EE开发的颠覆者 SPRING BOOT实战》高清带书签

    涵盖使用Spring Boot 进行Java EE 开发的绝大数应用场景,包含:Web 开发、数据访问、安全控制、批处理、异步消息、系统集成、开发与部署、应用监控、分布式系统开发等。 当你学完本书后,你将能使用Spring Boot ...

    Spring.net实战开发

    它能够提供宽广范围的功能,例如依赖注入、面向方面编程(AOP)、数据访问抽象, 以及ASP DOTNET集成等。基于java的spring框架的核心概念和价值已被应用到.NET。Spring DOTNET 1.0 包含一个完全功能的依赖注入容器和AOP...

Global site tag (gtag.js) - Google Analytics