1.操作BLOB/CLOB数据
BLOB被称作二进制对象,CLOB被称作大文本对象。他们在不同的数据库中可能名字也不相同,比如:在Sql Server中就是IMAGE/TEXT,在Mysql中就是BLOB/LONGTEXT,处理方式也不完全相同,在Mysql中LONGTEXT处理方式和VARCHAR是相同的。BLOB可能以块方式处理,也可以以流方式处理。
首先需要配置LobHandler,这个类可以专业的处理BLOB/CLOB
注意,如果使用的是Oracle 9i需要特殊处理,配置NativeJdbcExtrator,并且需要将Extrator加入到JdbcTemplate和LobHandler的对象属性中
下面我们来看下LOB的处理,
@Repository public class PostDao { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private LobHandler lobHandler; public void addPost(final Post post) { String sql = "INSERT INTO t_post(user_id,post_text,post_attach) VALUES(?,?,?)"; jdbcTemplate.execute(sql, new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) { @Override protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, DataAccessException { ps.setInt(1, post.getUserId()); lobCreator.setClobAsString(ps, 2, post.getPostText()); lobCreator.setBlobAsBytes(ps, 3, post.getPostAttach()); } }); } }
需要使用AbstractLobCreatingPreparedStatementCallback类来代替普通的Callback类,还需要向它的构造函数中传入lobHander。
以块数据的方式处理LOB数据
以byte[]的方式来处理
public ListgetAttaches(final int userId) { String sql = "SELECT post_id,post_attach,post_text FROM t_post WHERE user_id=? and post_attach IS NOT NULL"; return jdbcTemplate.query(sql, new Object[] { userId }, new RowMapper (){ public Post mapRow(ResultSet rs, int rowNum) throws SQLException { int postId = rs.getInt("post_id"); byte[] attach = lobHandler.getBlobAsBytes(rs, "post_attach"); String text = lobHandler.getClobAsString(rs, "post_text"); Post post = new Post(); post.setPostId(postId); post.setUserId(userId); post.setPostAttach(attach); post.setPostText(text); return post; } }); }
以流的方式来处理LOB对象
如果LOB对象很大,比如100M,如果采用块的方式来处理,将会消耗很大的内存,所以采用流的方式来处理比较好。
public void getAttach(final int postId, final OutputStream os) { String sql = "SELECT post_attach FROM t_post WHERE post_id=?"; jdbcTemplate.query(sql, new Object[] { postId }, new AbstractLobStreamingResultSetExtractor() { @Override protected void streamData(ResultSet rs) throws SQLException, IOException, DataAccessException { InputStream is = lobHandler.getBlobAsBinaryStream(rs, 1); if(is != null) FileCopyUtils.copy(is, os); } }); }
2.自增键和行集
自增键有两种方式,一种是Oracle基于序列的方式,一种是基于表的方式,这里仅描述针对表的方式。自增键的基类是DataFieldMaxValueIncrementer,有兴趣可以自己看下。
在DAO类中,注入以上Bean,就可以使用incre.nextIntValue()获取主键了。
行集SqlRowSet的内容不是很清楚,这里暂时跳过。
3.其他类型的JdbcTemplate
主要是NamedParameterJdbcTemplate,下面看下实例。
@Repository public class PostDao { @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void addPostByNamedParams(final Post post) { String sql = "INSERT INTO t_post(user_id,post_text) VALUES(:userId,:postText)"; SqlParameterSource sps = new BeanPropertySqlParameterSource(post); namedParameterJdbcTemplate.update(sql, sps); } public void addPostByMapSqlParams(final Post post) { String sql = "INSERT INTO t_post(user_id,post_text) VALUES(:userId,:postText)"; SqlParameterSource sps = new MapSqlParameterSource() .addValue(":userId", post.getUserId()) .addValue(":postText", post.getPostText()); namedParameterJdbcTemplate.update(sql, sps); } }