《Spring》(十七)---- JDBC访问数据

基于JdbcTemplate的数据查询

用于查询的回调接口定义主要有以下三种:

  1. ResultSetExtractor
public interface ResultSetExtractor {
    Object extractData(ResultSet rs) throws SQLException, DataAccessException;
}

  2. RowCallbackHandler  只关注单行结果的处理。

public interface RowCallbackHandler {
    void processRow(ResultSet rs) throws SQLException;
}

  3. RowMapper 只关注单行结果。

public interface RowMapper {
    Object mapRow(ResultSet rs, int rowNum) throws SQLException;
}

Example: 

package com.ivy.SpringJdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;

public class CallbackDemo {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public List<Customer> getCustomersByResultSetExtractor() {
        List<Customer> customerList = (List<Customer>)jdbcTemplate.query("select * from customer", new ResultSetExtractor<List<Customer>>() {

            @Override
            public List<Customer> extractData(ResultSet rs) throws SQLException,
                    DataAccessException {
                List<Customer> customers = new ArrayList<Customer>();
                while(rs.next()) {
                    Customer customer = new Customer();
                    customer.setFirstName(rs.getString(1));
                    customer.setLastName(rs.getString(1));
                    customer.setAge(rs.getInt(3));
                    customers.add(customer);
                }
                return customers;
            }
            
        });
        return customerList;
    }
    
    public List<Customer> getCustomersByRowCallbackHandler() {
        final List<Customer> customers = new ArrayList<Customer>();
        jdbcTemplate.query("select * from customer", new RowCallbackHandler() {

            @Override
            public void processRow(ResultSet rs) throws SQLException {
                Customer customer = new Customer();
                customer.setFirstName(rs.getString(1));
                customer.setLastName(rs.getString(1));
                customer.setAge(rs.getInt(3));
                customers.add(customer);
            }
            
        });
        return customers;
    }
    
    public List<Customer> getCustomersByRowMapper() {
        List<Customer> customers = jdbcTemplate.query("select * from customer", new RowMapper<Customer>() {

            @Override
            public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
                Customer customer = new Customer();
                customer.setFirstName(rs.getString(1));
                customer.setLastName(rs.getString(1));
                customer.setAge(rs.getInt(3));
                return customer;
            }
        });
        return customers;
    }
}

基于JdbcTemplate的数据更新

int update(String sql)

int update(String sql, Object[] args)

int update(String sql, Object[] args, int[] argTypes)

批量更新数据

int[] batchUpdate(String[] sql)

int[] batchUpdate(String sql, BatchPreparedStatementSetter pss)

Example

package com.ivy.SpringJdbc;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;

public class BatchUpdateDemo {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public int[] insertNewCustomers(final List<Customer> customers) {
        return jdbcTemplate.batchUpdate("insert into customer value(?,?,?)", new BatchPreparedStatementSetter() {
            
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Customer customer = (Customer)customers.get(i);
                ps.setString(1, customer.getFirstName());
                ps.setString(2, customer.getLastName());
                ps.setInt(3, customer.getAge());
            }
            
            @Override
            public int getBatchSize() {
                return customers.size();
            }
        });
    }
}

调用存储过程

存储过程是定义于数据库服务器端的计算单元。对于涉及多表数据而只使用SQL无法完成的计算,我们可以通过在数据库服务器端编写并部署存储过程的方式来实现。相对于将这些计算逻辑转移到客户端进行,使用存储过程的好处在于,可以避免像客户端计算那样在网络间来回传送数据导致的性能损失,因为存储过程的所有计算全部在服务器端完成。如果计算设计多个数据表,大量的数据查询和更新,那么使用存储过程代替客户端计算是比较合适的做法。

例如

CREATE PROCEDURE CountTable(IN tableName varchar(1000), OUT sqlStr varchar(1000), INOUT v INT)
BEGIN
    set @flag = v;
    set @sql = CONCAT('select count(*) into @res from'', tableName, 'where ACTIVE_FLAG=?');
    PREPARE stmt FROM @sql;
    EXECUTE stmt using @flag;
    DEALLOCATE PREPARE stmt;
    set v = @res;
    set sqlStr = @sql;
END

 

Object result = jdbcTemplate.execute("call CountTable(?,?,?)", new CallableStatementCallback() {

            @Override
            public Object doInCallableStatement(CallableStatement cs)
                    throws SQLException, DataAccessException {
                cs.setString(1, "tableName");
                cs.setInt(3, 1);
                cs.registerOutParameter(2, Types.INTEGER);
                cs.registerOutParameter(3, Types.INTEGER);
                
                cs.execute();
                
                Map resultMap = new HashMap();
                resultMap.put("SQL", cs.getString(2));
                resultMap.put("COUNT", cs.getInt(3));
                return resultMap;
            }
            
        });

递增主键生成策略的抽象

 1,基于独立主键表的DataFieldMaxValueIncrementer。它依赖于为每个数据表单独定义的主键表,主键表中定义的主键可以根据需要获取并递增,并且可以设置每次获取的CacheSize以减少访问数据库资源的频度。

 2,基于数据库Sequence的DataFiledMaxValueIncrementer。数据库本身支持基于Sequence的主键生成。

String中的LOB类型处理

Spring提出一套基于LOB数据处理类,用于屏蔽各数据库驱动在处理LOB数据方式上的差异性。

public interface LobHandler {
    byte[] getBlobAsBytes(ResultSet rs, String columnName) throws SQLException;
    byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException;
    InputStream getBlobAsBinaryStream(ResultSet rs, String columnName) throws SQLException;
    InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException;
    String getBlobAsString(ResultSet rs, String columnName) throws SQLException;
    String getBlobAsString(ResultSet rs, int columnIndex) throws SQLException;
    InputStream getBlobAsAsciiStream(ResultSet rs, String columnName) throws SQLException;
    InputStream getBlobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException;
    Reader getBlobAsCharStream(ResultSet rs, String columnName) throws SQLException;
    Reader getBlobAsCharStream(ResultSet rs, int columnIndex) throws SQLException;
    LobCreator getLobCreator();
}

  LobCreator的职责主要在于LOB数据的创建,它让我们能够以统一的方式创建LOB数据。我们将在插入或者更新LOB数据的时候使用它。

 DefaultLobHandlerDemo.java

package com.ivy.SpringJdbc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;

public class DefaultLobHandlerDemo {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public void saveImage() throws FileNotFoundException {
        final File imageFile = new File("snow_image.jpg");
        final InputStream ins = new FileInputStream(imageFile);
        LobHandler lobHandler = new DefaultLobHandler();
        jdbcTemplate.execute("insert into images(id, filename, entity, description) values(?,?,?,?)", new AbstractLobCreatingPreparedStatementCallback(lobHandler) {

            @Override
            protected void setValues(PreparedStatement ps, LobCreator lobCreator)
                    throws SQLException, DataAccessException {
                ps.setInt(1, 2);
                ps.setString(2, "snow_image.jpg");
                lobCreator.setBlobAsBinaryStream(ps, 3, ins, (int)imageFile.length());
                ps.setString(4, "nothing to say");
            }

            
        });
        IOUtils.closeQuietly(ins);
    }
}

NamedParameterJdbcTemplate

example 1 :

DataSource dataSource = ...;
NamedParameterJdbcTemplate npJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);

SqlParameterSource parameterSource = new MapSqlParameterSource("filename","snow_image.jpg");
int count = npJdbcTemplate.queryForInt("select count(*) from images where filaname=:filename", parameterSource);

example 2 :

DataSource dataSource = ...;
NamedParameterJdbcTemplate npJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);

Image image = new Image();
image.setFilename("snow_image.jpg");


SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(image);
int count = npJdbcTemplate.queryForInt("select count(*) from images where filaname=:filename", parameterSource);

SimpleJdbcTemplate

SimpleJdbcTemplate集JdbcTemplate和NamedParameterJdbcTemplate的功能于一身。

example:

package com.ivy.SpringJdbc;

import java.awt.Image;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.activation.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobHandler;

public class SimpleJdbcTemplateDemo {

    @Autowired
    private DataSource dataSource;
    
    public void test() {
        SimpleJdbcTemplate simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
        final LobHandler lobHandler = new DefaultLobHandler();
        String SQL = "select count(*) from images where filename = ? and description = ?";
        ParameterizedRowMapper<Image> rowMapper = new ParameterizedRowMapper<T>() {

            @Override
            public T mapRow(ResultSet rs, int rowNum) throws SQLException {
                Image image = new Image();
                image.setId(rs.getInt(1));
                image.setFilename(rs.getString(2));
                image.setEntity(lobHandler.getBlobAsBytes(rs, 3));
                image.setDescription(rs.getString(4));
                return image;
            }
        };
     Image image = simpleJdbcTemplate.queryForObject(SQL, rowMapper, "snow_image.jpg", "nothing to say");
} }

DataSource访问方式

1, 本地DataSource访问

在容器的配置文件中进行简单的配置即可。

2,远程DataSource访问

对于运行于应用服务器的程序或者分布式应用来说,通过JNDI访问DataSource是最常见方式

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jdniName">
        <value>java:env/myDataSource</value>
    </property>
</bean>
原文地址:https://www.cnblogs.com/IvySue/p/6610380.html