【需求】:1.用户功能中要求实现对用户照片的上传、以及用户照片查看功能。
2.为了提升数据的移植性,要求照片文件以流的形式保存到数据库,提供跨数据库的机制。
【思考】:1.传统意义上的角度来看,文件应以路径的形式存储到数据库,通过路径来读写文件流,从而完成对照片的上传、预览,但是
数据库如果要备份、转移,项目要重新部署到其他路径上,那我们又要把存放照片的文件copy过来,把项目的路径更新一次,
由于考虑到项目部署的空间和范围,以及数据库流动性大的问题,这种情况显然不成立。
2.系统采用的SSH框架,实现跨数据库很简单,只需改对datasource的配置进行修改即可。前期表结构以及entity对象,包括hbm文件
都相应的生成好了,本着弹性原则,没有去修改user中pic字段的映射,而hibernate本身对blob或者clob字段处理显得很繁琐,不如实际
jdbc处理的好,所以决定用springjdbc来实现,解决了jdbc控制流关闭、连接等以及hibernate自身对特殊字段处理一些不便利的操作。
【实现部分】:
1. 上传(springJdbc实现对用户照片写===>对用户照片中 blob字段的更新操作)
- public void upload(final File file, final String userId) throws Exception {
- final FileInputStream fis = new FileInputStream(file);
- String sql = "update ST_USER set PIC=? where SM_USER_ID=?";
- JdbcTemplate jdbcTemplate = jdbcDao.getJdbcTemplate();
- jdbcTemplate.execute(sql,
- new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
- protected void setValues(PreparedStatement ps,
- LobCreator lobCreator) throws SQLException {
- int length = (int) file.length();
- lobCreator.setBlobAsBinaryStream(ps, 1, fis, length);
- ps.setString(2, userId);
- }
- });
- fis.close();
- }
复制代码【备注】:1.通过前台获取的file,转换成fileInputStream,在springJdbc进行操作之前对照片这个字段进行设置,通过AbstractLobCreatingPreparedStatement 来对照片字段设置流。
2.值得注意的是lobHandler需要进行配置,它是专门针对clob或者blob进行处理的handler,配置如下:
<!-- lobhander 用于处理BLOB 或者 CLOB 字段 -->
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" lazy-init="true" />
注:加入spring配置文件即可,然后在具体实现类中进行进行依赖注入即可得到。
2.预览 (springJdbc实现对用户照片读===>读取照片流文件并将结果集转换成byte数组):
- public byte [] preview(String userId) throws Exception {
- String sql = "select PIC from ST_USER where SM_USER_ID=?";
- final String BLOB_KEY="BLOB";
- JdbcTemplate jdbcTemplate = jdbcDao.getJdbcTemplate();
- List<Map<String, byte[]>> list = jdbcTemplate.query(sql,new Object[]{userId}, new RowMapper() {
- public Object mapRow(ResultSet rs, int i) throws SQLException {
- Map<String, byte[]> results = new HashMap<String, byte[]>();
- byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "PIC");
- results.put(BLOB_KEY, blobBytes);
- return results;
- }
- });
- return list.get(0).get(BLOB_KEY);
- }
复制代码 【备注】:读取要比存储简单的多,通过jdbc查询,我们得到结果集,在结果集我们将读取出来的照片转换一下,变成byte数组,然后返回。
【后续】:这部分功能只是体现在持久层的实现,如果大家感兴趣,我会放出上传和预览功能的前台端实现(struts2+ext)。