您现在的位置是:首页 >技术交流 >Spring JdbcTemplate网站首页技术交流

Spring JdbcTemplate

今天月亮不加班 2024-10-06 00:01:05
简介Spring JdbcTemplate

三联支持 一起鼓励 一起进步

JdbcTemplate



一、JdbcTemplate概述

用于和数据库交互的,实现对表的CRUD操作。

它是Spring框架提供的一个对象,是对原始Jdbc API对象的简单封装。Spring框架为我们提供了很多的操作模板类。

操作关系型数据库的:JdbcTemplate、HibernateTemplate

操作noSql数据库的:RedisTemplate

操作消息队列的:JmsTemplate

JdbcTemplate在spring-jdbc-5.0.2.RELEASE.jar中,我们在导包的时候,除了要导入这个jar包,还需要导入和事务相关的spring-tx-5.0.2.RELEASE.jar。

用法示例

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>12.1.0.1-atlassian-hosted</version>
</dependency>

编写测试方法:

public class JdbcTemplateDemo1 {
    public static void main(String[] args) {

        // 准备数据源: Spring内置数据源
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@localhost:1521/orcl");
        dataSource.setUsername("springTest");
        dataSource.setPassword("tiger");

        // 创建JdbcTemplate对象
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.execute("insert into account(id, name, money) values ('04', 'dddd', 200)");
    }
}

二、JdbcTemplate的CRUD操作

使用IoC管理JdbcTemplate

在bean.xml中配置bean:

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">
    </property>
    <property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl">
    </property>
    <property name="username" value="springTest"></property>
    <property name="password" value="tiger"></property>
</bean>

1.新增

jdbcTemplate.update("insert into account (id, name, money) values (?, ?, ?)", "06", "ffff", 1000);

2.更新

jdbcTemplate.update("update account set name=?, money=? where id=?",  "ffff", 800, "06");

3.删除

jdbcTemplate.update("delete from account where id=?", "06");

4.查询获取List

自定义数据库实体类的属性和数据库结果集映射。

public class JdbcTemplateDemo3 {
    public static void main(String[] args) {
        List<Account> accounts = 
            jdbcTemplate.query("select * from account where money > ?", 
                               new AccountRowMapper(), 300);
        accounts.forEach(System.out::println);
    }
}
class AccountRowMapper implements RowMapper<Account> {

    /**
     * 把结果集的数据封装到Account中,然后由Spring把每个Account加到集合中
     */
    @Override
    public Account mapRow(ResultSet resultSet, int i) throws SQLException {
        Account account = new Account();
        account.setId(resultSet.getString("id"));
        account.setName(resultSet.getString("name"));
        account.setMoney(resultSet.getFloat("money"));
        return account;
    }
}

使用Spring自带的BeanPropertyRowMapper进行映射

List<Account> accounts = 
    jdbcTemplate.query("select * from account where money > ?", 
                       new BeanPropertyRowMapper<Account>(Account.class), 300);
accounts.forEach(System.out::println);

5.查询一个

获取到多个后,判断是否为空,获取第一个

List<Account> accounts = 
    jdbcTemplate.query("select * from account where id = ?", 
           				new BeanPropertyRowMapper<Account>(Account.class), "03");
System.out.println(accounts.isEmpty()? "无结果" : accounts.get(0));

6.查询一个值(聚合函数)

使用聚合函数返回一行一列,但不加group by 子句

int count = 
  jdbcTemplate.queryForObject("select count(*) from account where money > ?",
                              Integer.class, 200f);
System.out.println(count);

三、编写JdbcDaoSupport去除dao层重复代码

Spring中原生就提供了JdbcDaoSupport类,下面的示例只是演示JdbcDaoSupport的实现原理

原来的dao层每一个实现类内部都需要注入JdbcTemplate,可以编写一个父类JdbcDaoSupport让dao层实现类都继承该类。

JdbcDaoSupport.java

public class JdbcDaoSupport {
    private JdbcTemplate jdbcTemplate;

    // 只注入dataSource也可以get到jdbcTemplate对象
    public void setDataSource(DataSource dataSource) {
        jdbcTemplate = createJdbcTemplate(dataSource);
    }
    private JdbcTemplate createJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

AccountDaoImpl.java

public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

    @Override
    public Account findAccountById(String id) {
        List<Account> accounts = super.getJdbcTemplate().
            query("select * from account where id=?", 
                  new BeanPropertyRowMapper<>(Account.class), id);
        return accounts.isEmpty() ? null : accounts.get(0);
    }

    @Override
    public void updateAccount(Account account) {
        // 使用super.getJdbcTemplate()获取到jdbcTemplate对象
        super.getJdbcTemplate().
            update("update account set name=?, money=? where id=?",
                   account.getName(), account.getMoney(), account.getId());
    }
}

在xml中配置注入dataSource:

<bean id="accountDao" class="com.study.dao.impl.AccountDaoImpl">
    <property name="dataSource" ref="dataSource">
    </property>
</bean>

<bean id="dataSource" 
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">
    </property>
    <property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl">
    </property>
    <property name="username" value="springTest"></property>
    <property name="password" value="tiger"></property>
</bean>

四、Spring的声明式事务控制

事务的接口spring-tx-5.0.2.RELEASE.jar中。
Spring的事务控制都是基于AOP的,它既可以使用编程的方式实现,也可以使用配置的方式实现

1.Spring中的事务控制API

1.PlatformTransactionManager

PlatformTransactionManager接口提供事务操作的方法,包含3个具体的操作:

● 获取事务状态信息
TransactionStatus getTransaction(TransactionDefinition definition)

● 提交事务
void commit(TransactionStatus status)

● 回滚事务
void rollback(TransactionStatus status)

常用的实现类:

org.springframework.jdbc.datasource.DataSourceTransactionManager:使用Spring JDBC或iBatis进行持久化数据时使用。

org.springframework.orm.hibernate5.HibernateTransactionManager:使用Hibernate版本进行持久化数据时使用。

2.TransactionDefinition

它是事务的定义信息对象,里面有如下方法:

● String getName()
获取事务对象名称

● int getIsolationLevel()
设置事务隔离级别

● int getPropagationBehavior()
获取事务传播行为

● int getTimeout()
获取事务超时时间

● boolean isReadOnly()
获取事务是否只读

事务隔离级别反映事务提交并发访问时的处理态度

● ISOLATION_DEFAULT
默认级别,采用数据库的隔离级别

● ISOLATION_READ_UNCOMMITTED
可以读取未提交的数据

● ISOLATION_READ_COMMITED
只能读取已提交的数据,解决脏读问题

● ISOLCATION_REPEATABLE_READ
是否读取其他事务提交修改后的数据,解决不可重复读问题

● ISOLATION_SERIALIZABLE
是否读取其他事务提交添加后的数据,解决幻影读问题。

事务传播行为:

● REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)

● SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式进行(没有事务)

● MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常

● REQUERS_NEW
新建事务,如果当前在事务中,就把当前事务挂起

● NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

● NEVER
以非事务方式运行,如果当前存在事务,抛出异常

● NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行REQUIRED类似的操作。

3.TransactionStatus

此接口提供的是事务具体的运行状态。

TransactionStatus接口描述了某个时间点上事务对象的状态信息,包含6个具体操作:

● void flush()
刷新事务

● boolean hasSavepoint()
获取是否存在存储点(按步提交回滚,类似游戏存档)

● boolean isCompleted()
获取事务是否完成

● boolean isNewTransaction()
获取事务是否为新事务

● boolean isRollbackOnly()
获取事务是否回滚

● void setRollbackOnly()
设置事务回滚

2.纯注解配置的声明式事务配置

在resources中创建数据库连接配置文件:jdbcConfig.properties

jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.userName=springTest
jdbc.password=tiger
jdbc.url=jdbc:oracle:thin:@localhost:1521/orcl

创建数据库连接配置类

public class JdbcConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.userName}")
    private String userName;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.password}")
    private String password;
    
    @Bean("jdbcTemplate")
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean("dataSource")
    public DataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
        dataSource.setUrl(url);
        return dataSource;
    }
}

创建事务配置类

public class TransactionConfiguration {

    @Bean("transactionManager")
    public PlatformTransactionManager createTransactionManager(
        DataSource datasource) {
        return new DataSourceTransactionManager(datasource);
    }
}

创建总配置类

@Configuration
@ComponentScan("com.study")
@PropertySource("jdbcConfig.properties")
@EnableTransactionManagement  // 开启事务支持
@Import({JdbcConfiguration.class, TransactionConfiguration.class})
public class SpringConfiguaration {
}

总结

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。