科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Spring让LOB数据操作变得简单易行

Spring让LOB数据操作变得简单易行

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文讲解了在 Spring 中处理 LOB 数据的原理和方法

作者:陈雄华 来源:Impress Watch中文站 2007年10月13日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共5页)

 以块数据方式读取 LOB 数据

  您可以直接用数据块的方式读取 LOB 数据:用 String 读取 CLOB 字段的数据,用 byte[] 读取 BLOB 字段的数据。在 PostJdbcDao 中添加一个 getAttachs() 方法,以便获取某一用户的所有带附件的帖子:

  清单 7. 以块数据访问 LOB 数据

public List getAttachs(final int userId){ 
  String sql = "SELECT post_id,post_attach FROM t_post “+ 
“where user_id =? and post_attach is not null "; 
  return getJdbcTemplate().query( 
        sql,new Object[] {userId}, 
        new RowMapper() { 
          public Object mapRow(ResultSet rs, int rowNum) throws SQLException { 
            int postId = rs.getInt(1); 
            ① 以二进制数组方式获取 BLOB 数据。 
            byte[] attach = lobHandler.getBlobAsBytes(rs, 2);  
            Post post = new Post(); 
            post.setPostId(postId); 
            post.setPostAttach(attach); 
            return post; 
          } 
        }); 
} 

  通过 JdbcTemplate 的 List query(String sql, Object[] args, RowMapper rowMapper) 接口处理行数据的映射。在 RowMapper 回调的 mapRow() 接口方法中,通过 LobHandler 以 byte[] 获取 BLOB 字段的数据。

  以流数据方式读取 LOB 数据

  由于 LOB 数据可能很大(如 100M),如果直接以块的方式操作 LOB 数据,需要消耗大量的内存资源,对应用程序整体性能产生巨大的冲击。对于体积很大的 LOB 数据,我们可以使用流的方式进行访问,减少内存的占用。JdbcTemplate 为此提供了一个 Object query(String sql, Object[] args, ResultSetExtractor rse) 方法,ResultSetExtractor 接口拥有一个处理流数据的抽象类 org.springframework.jdbc.core.support.AbstractLobStreamingResultSetExtractor,可以通过扩展此类用流的方式操作 LOB 字段的数据。下面我们为 PostJdbcDao 添加一个以流的方式获取某个帖子附件的方法:

  清单 8. 以流方式访问 LOB 数据

… 
public void getAttach(final int postId,final OutputStream os){ ① 用于接收 LOB 数据的输出流 
  String sql = "SELECT post_attach FROM t_post WHERE post_id=? "; 
  getJdbcTemplate().query( 
      sql, new Object[] {postId}, 
      new AbstractLobStreamingResultSetExtractor() { ② 匿名内部类 
③ 处理未找到数据行的情况 
protected void handleNoRowFound() throws LobRetrievalFailureException { 
          System.out.println("Not Found result!"); 
        } 
        ④ 以流的方式处理 LOB 字段 
        public void streamData(ResultSet rs) throws SQLException, IOException { 
          InputStream is = lobHandler.getBlobAsBinaryStream(rs, 1); 
          if (is != null) { 
            FileCopyUtils.copy(is, os); 
          } 
        } 
      } 
  ); 
} 

  通过扩展 AbstractLobStreamingResultSetExtractor 抽象类,在 streamData(ResultSet rs) 方法中以流的方式读取 LOB 字段数据,如 ④ 所示。这里我们又利用到了 Spring 的工具类 FileCopyUtils 将输入流的数据拷贝到输出流中。在 getAttach() 方法中通过入参 OutputStream os 接收 LOB 的数据,如 ① 所示。您可以同时覆盖抽象类中的 handleNoRowFound() 方法,定义未找到数据行时的处理逻辑。

  在 JPA 中操作 LOB 数据

  在 JPA 中 LOB 类型的持久化更加简单,仅需要通过特殊的 LOB 注释(Annotation)就可以达到目的。我们对 Post 中的 LOB 属性类型进行注释:

  清单 9. 注释 LOB 类型属性

package com.baobaotao.domain; 
… 
import javax.persistence.Basic; 
import javax.persistence.Lob; 
import javax.persistence. Column; 
@Entity(name = "T_POST") 
public class Post implements Serializable { 
  … 
  @Lob ①-1 表示该属性是 LOB 类型的字段 
  @Basic(fetch = FetchType.EAGER) ①-2 不采用延迟加载机制 
  @Column(name = "POST_TEXT", columnDefinition = "LONGTEXT NOT NULL") ①-3 对应字段类型 
  private String postText; 

  @Lob ②-1 表示该属性是 LOB 类型的字段 
  @Basic(fetch = FetchType. LAZY) ②-2 采用延迟加载机制 
  @Column(name = "POST_ATTACH", columnDefinition = "BLOB") ②-3 对应字段类型 
  private byte[] postAttach; 
… 
} 

  postText 属性对应 T_POST 表的 POST_TEXT 字段,该字段的类型是 LONTTEXT,并且非空。JPA 通过 @Lob 将属性标注为 LOB 类型,如 ①-1 和 ②-1 所示。通过 @Basic 指定 LOB 类型数据的获取策略,FetchType.EAGER 表示非延迟加载,而 FetchType.LAZY 表示延迟加载,如 ①-2 和 ②-2 所示。通过 @Column 的 columnDefinition 属性指定数据表对应的 LOB 字段类型,如 ①-3 和 ②-3 所示。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章