Spring学习笔记之通过Spring和JDBC征服数据库

1.Spring的数据访问哲学

为了将数据访问层(DAO)与应用程序的其他部分隔离开来,Spring采用的方式之一就是提供统一的异常体系,这个异常体系用在了它支持的所有持久化方案中。

1.1Spring的数据访问异常体系

写JDBC的时候,我们常常需要捕获SQLException,而可能导致SQLException的问题有很多,比如下面这些:

  • 应用程序无法连接数据库
  • 要执行的查询存在语法错误
  • 查询中所使用的表和/或列不存在
  • 试图插入或更新的数据违反了数据库约束

而SQLException并不能告诉我们导致抛出异常的原因具体是哪一个。

Spring JDBC提供了很多与平台无关的持久化异常,而且这些异常都继承自DataAccessException。DataAccessException的特殊之处在于他是一个非检查性异常。也就是说,不像SQLException你必须捕获它,DataAccessException可以让你不必捕获Spring所抛出的数据访问异常。这是因为Spring认为触发异常的很多问题是不能在catch代码块中修复的

1.2数据访问模板化

设计模式:模板方法模式
模板方法将过程中与特定实现相关的部分委托给接口,而这个接口的不同实现定义了过程的具体行为。
Spring将数据访问过程中固定的和可变的部分明确划分为两个不同的类:模板(template)和回调(callback)。模板管理过程中固定的部分,而回调处理自定义的数据访问代码。
Spring的模板处理数据访问的固定部分——事物控制、资源管理以及处理异常。同时,应用程序相关的数据访问——语句、绑定参数以及整理结果集——在回调的实现中处理。
Spring提供的数据访问模板,分别适用于不同的持久化机制

模板类(org.springframework.*)用途
jca.cci.core.CciTemplateJCA CCI连接
jdbc.core.JdbcTemplateJDBC连接
jdbc.core.namedparam.NamedParameterJdbcTemplate支持命名参数的JDBC连接
jdbc.core.simple.SimpleJdbcTemplate通过Java5简化后的JDBC连接(Spring3.1中已经废弃)
orm.hibernate3.HibernateTemplateHibernate 3.x以上的Session
orm.ibatis.SalMapClientTemplateiBATIS SqlMap客户端
orm.jdo.JdoTemplateJava 数据对象(Java Data Object)实现
orm.jpa.JpaTemplateJava 持久化API的实体管理器

2.配置数据源

无论选择Spring的哪种数据访问方式,你都需要配置一个数据源的引用。Spring提供了在Spring上下文中配置数据源bean的多种方式,包括:

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

2.1使用JNDI数据源

XML配置:

<jee:jndi-loopup id="dataSource" 
    jndi-name="/jdbc/spitterDS"
    resource-ref="true" />

其中jndi-name属性用于指定JNDI中资源的名称。如果只设置了jndi-name属性,那么就会根据指定的名称查找数据源。但是,如果应用程序运行在Java应用服务器中,你需要将resource-ref属性设置为true,这样给定的jndi-name将会自动添加“java:comp/env/”前缀。

Java配置:

@Bean
    public JndiObjectFactoryBean dataSource(){
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setJndiName("jdbc/SpitterDS");
        bean.setResourceRef(true);
        bean.setProxyInterface(javax.sql.DataSource.class);
        return bean;
    }

2.2使用数据源连接池

Spring并没有提供数据源连接池的实现,但是我们有多项可用的方案,包括如下开源的实现:

  • Apache Commons DBCP
  • c3p0
  • BoneCP

以DBCP为例:
XML配置:

<bean id="dataSource" class="org,apache.commons.dbcp.basicDataSource"
    p:driverClassName="org.h2.Driver"
    P:url="jdbc:h2:tcp://localhost/~/spitter"
    p:uasername="sa"
    p:initialSize="5"
    p:password=""
    p:maxActive="10"/>

Java 配置

@Bean 
    public BasicDataSource dataSource(){
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName("org.h2.Driver");
        ds.setUrl("jdbc:h2:tcp://localhost/~/spitter");
        ds.setUsername("sa");
        ds.setPassword("");
        ds.setInitialSize(5);
        ds.setMaxActive(10);
        return ds;
    }

BasicDataSource的池配置属性

池配置属性所指定的内容
initialSize池启动时创建的连接数量
maxActive同一时间可从池中分配的最多连接数。如果设置为0,表示无限制
maxIdle池里不会被释放的最多空闲连接数。如果设置为0,表示无限制
maxOpenPreparedStatments在同一时间能够从语句池中分配的预处理语句的最大数量。如果设置为0,表示无限制
maxWait在抛出异常之前,池等待连接回收的最大时间。如果设置为-1,表示无限等待
minEvictableIdleTimeMillis连接在池中保持空闲而不被回收的最大时间
minIdle在不创建新连接的情况下,池中保持空闲的最小连接数
poolPreparedStatements是否对预处理语句进行池管理

2.3基于JDBC驱动的数据源

在Spring中,通过JDBC驱动定义数据源是最简单的配置方式。Spring提供了三个这样的数据源类供选择:

  • DriverManagerDataSource:在每个连接请求时都返回一个新建的连接。与DBCP的BasicDataSource不同,由DriverManagerDataSource提供的连接并没有进行池化管理;
  • SimpleDriverDataSource:与DriverManagerDataSource的工作方式类似,但是它直接使用JDBC驱动,来解决在特定环境下的类加载问题,这样的环境包括OSGi容器;
  • SingleConnectionDataSource:在每个连接请求时都会返回同一个的连接。尽管SingleConnectionDataSource不是严格意义上的连接池数据源,但是你可以将其视为只有一个连接的池。

以上这些数据源的配置与DBCP BasicDataSource的配置类似。例如,如下就是配置DriverManagerDataSource的方法
XML:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" 
p:driverClassName="org.h2.Driver"
p:url="jdbc:h2:tcp://localhost/~/spitter"
P:username="sa"
p:password=""/>

Java配置:

@Bean 
    public DriverManagerDataSource dataSource(){
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("org.h2.Driver");
        ds.setUrl("jdbc:h2:tcp://localhost/~/spitter");
        ds.setUsername("sa");
        ds.setPassword("");
        return ds;
    }

2.4使用嵌入式的数据源

嵌入式数据库作为应用的一部分运行,而不是应用连接的独立数据库服务器。对于开发和测试来讲,嵌入式数据库是很好的可选方案。这是因为每次重启应用或运行测试的时候,都能够重新填充测试数据。
Java配置:

@Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .addScript("classpatch:schema.sql")
                .addScript("classpatch:test-data.sql")
                .build();
    }

2.5使用profile选择数据源

Java配置:

//生产环境的数据源
    @Profile("production")
    @Bean
    public JndiObjectFactoryBean dataSource(){
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setJndiName("jdbc/SpitterDS");
        bean.setResourceRef(true);
        bean.setProxyInterface(javax.sql.DataSource.class);
        return bean;
    }

    //QA数据源
    @Profile("qa")
    @Bean 
    public BasicDataSource data(){
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName("org.h2.Driver");
        ds.setUrl("jdbc:h2:tcp://localhost/~/spitter");
        ds.setUsername("sa");
        ds.setPassword("");
        ds.setInitialSize(5);
        ds.setMaxActive(10);
        return ds;
    }

    //开发数据源
    @Profile("development")
    @Bean
    public DataSource embeddedDataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .addScript("classpatch:schema.sql")
                .addScript("classpatch:test-data.sql")
                .build();
    }

3.在Spring中使用JDBC

使用JDBC模板
Spring的JDBC框架承担了资源管理和异常处理的工作,从而简化了JDBC代码,让我们只需编写从数据库读写数据的必需代码。
Spring为JDBC提供了三个模板类供选择:

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

从Spring3.1开始,SimpleJDBCTemplate已经被废弃,器Java5的特性被转移到了jdbcTemplate中,并且只有在你需要使用命名参数的时候,才需要使用NamedParameterJDBCTemplate。这样的话,对于大多数的JDBC任务来说,jdbcTemplate就是最好的可选方案。

使用jdbcTemplate来插入数据示例:

@Bean
    @Autowired
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
@Autowired
    private JdbcOperations jdbcTemplate;

    public void addSpitter(){
        jdbcTemplate.update("insert into spitter (username, password, fullname) values (?,?,?)", 
                "zhangsan","123456","zhangsanfeng");
    }

JdbcOperations 是一个接口,定义了JdbcTemplate 所实现的操作

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值