项目中使用SpringJdbcTemplate来操作数据库,简单方便实用(根据项目需求选择技术),目前用到Oracle10g数据库,由于其操作大文本使用Clob类型,故而研究了下jdbctemplate对clob和Blob的操作。
jdbctemplate对clob和blob的操作使用起来也很简单,网友提供很多实例和代码。例如:
http://hi.baidu.com/sileader/item/0b3335f512378fb731c19999
主要是利用jdbctemplate提供的两个类来操作:LobCreator和LobHandler,具体使用方法可参考该链接。
但是如果某个Bean属性字段太多的话,代码写起来将会很麻烦。是否可以提供一种通用的方法,让每个业务方法操作数据库Clob和Blob时候也可以像操作其他基本数据类型一样,一句代码就完成。例如插入和修改Bean:
public <T> void saveOrUpdate(String sql, T bean) { namedParameterJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(bean)); }
经过一些尝试和摸索,我使用反射和注解,写了一个通用类,可以操作查询、修改、添加,满足了项目中的需求。
1、定义了一个注解类,用于bean中属性上,主要是提供属性的数据库字段名以及其数据库类型。
/** * @description * @author aokunsang * @date 2013-7-4 */ @Target({ElementType.FIELD,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface PmcColumn { /** * 数据库中字段类型 * @return */ int type(); /** * 数据库中字段名 * @return */ String columnName(); /** * 查询列表时候是否忽略 * @return */ boolean ignore() default false; }
2、定义一个反射的工具类,反射操作属性字段的setter和getter方法注入和获取属性值、
/** * @description 对bean的反射操作 * @author aokunsang * @date 2013-7-3 */ public class BeanUtils { /** * @param obj 操作的对象 * @param att 操作的属性 * */ public static Object getter(Object obj, String att) { try { Method method = obj.getClass().getMethod("get" + StringUtils.capitalize(att)); return method.invoke(obj); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 注入数据 * @param obj 类的实例 * @param att 属性名 * @param value 注入数据内容 * @param type 返回的数据类型 * */ public static void setter(Object obj, String att, Object value, Class<?> type) { try { Method method = obj.getClass().getMethod("set" + StringUtils.capitalize(att), type); method.invoke(obj, value); } catch (Exception e) { e.printStackTrace(); } } /** * 获取某个属性字段的ignore信息 * @param field * @return */ public static boolean getPmcColumnIgnore(Field field){ Annotation annotation = field.getAnnotation(PmcColumn.class); boolean ignore = false; if(annotation!=null){ ignore = ((PmcColumn)annotation).ignore(); } return ignore; } /** * 获取某个属性的Type信息 * @param field * @return */ public static int getPmcColumnType(Field field){ Annotation annotation = field.getAnnotation(PmcColumn.class); int type = Types.VARCHAR; if(annotation!=null){ type = ((PmcColumn)annotation).type(); } return type; } /** * 获取某个属性的数据库中字段名 * @param field * @return */ public static String getPmcColumnName(Field field){ Annotation annotation = field.getAnnotation(PmcColumn.class); String columnName = ""; if(annotation!=null){ columnName = ((PmcColumn)annotation).columnName(); } return columnName; } }
3、定义一个对sql语句的转换类,sql语句进行转变,变成需要的字符串。
如:insert into t1 values(:a,:b,:c) ----> insert into t1(A,B,C) values(?,?,?);
或者update t1 set A=:a,B=:b where C=:c ----> update t1 set A=?,B=? where C=?
/** * 分割插入、修改的sql语句 * @param sql * @param columnMaps <属性名,数据库中字段名> * @return */ public static Map<String,List<String>> spQuerysql(String sql,Map<String,String> columnMaps){ if(StringUtils.isEmpty(sql)) return null; String _sql = sql + " "; String key = _sql.replaceAll(":(.+?),\\s*", "?,").replaceAll(":(.+?)[)]\\s*", "?)").replaceAll(":(.+?)\\s+", "? "); Map<String,List<String>> result = new HashMap<String, List<String>>(); List<String> fieldList = new LinkedList<String>(); Pattern pattern = Pattern.compile(":(.+?)[)|,|\\s*]"); Matcher matcher = pattern.matcher(_sql); StringBuffer insertString = new StringBuffer(); while(matcher.find()){ String value = matcher.group(1); fieldList.add(value); insertString.append(columnMaps.get(value)+ ","); } if(fieldList.isEmpty() || key.equals(_sql)) return null; StringBuffer key_sb = new StringBuffer(key); if(!key.trim().matches("insert\\s*into\\s*[\\w|_]+?\\(.*?\\)\\s*values.*") && !key.trim().contains("update")){ //判断insert语句是否有数据库字段,比如:insert into t1(ID,NAME) key_sb.insert(key_sb.indexOf("values")-1, "("+insertString.substring(0,insertString.length()-1)+")"); } result.put(key_sb.toString(), fieldList); return result; } /** * 通过查询语句分离出相应信息 * @param sql * @param clazz * @return */ public static Field[] spSelectSql(String sql,Class<?> clazz){ if(StringUtils.isEmpty(sql) || sql.indexOf("*")!=-1) return null; Map<String,Field> fieldMap = new HashMap<String,Field>(); List<Field> list = new ArrayList<Field>(); Field[] fields = clazz.getDeclaredFields(); //获取所有属性 for(Field field : fields){ fieldMap.put(BeanUtils.getPmcColumnName(field), field); } String[] columnNameArry = sql.substring(sql.toLowerCase().indexOf("select") + 6,sql.toLowerCase().indexOf("from")).replaceAll("\\s", "").split(","); for(String columnName : columnNameArry){ if(columnName.indexOf(".") != -1){ columnName = columnName.substring(columnName.indexOf(".")+1).trim(); }else{ columnName = columnName.trim(); } Field field = fieldMap.get(columnName); if(field==null) throw new PmcRuntimeException(String.format("你提供的SQL语句中的数据库字段[%s],没有在Bean中找到有效的属性值对应。", columnName)); list.add(field); } return list!=null ? list.toArray(new Field[]{}) : null; }
4、定义一个对clob和blob的通用类[[关键类],也可以说是已经存在的Dao类的扩展类。
/** * @description 增强版数据库操作类[添加对clob和blob的部分操作] * @author aokunsang * @date 2013-7-4 */ public class StGenericDao extends GenericDao { /** * 查询单条记录 * @param <T> * @param sql * @param clazz * @param args * @return */ public <T> T _find(String sql,final Class<T> clazz,Object... args){ printSqlInfo(sql,args!=null ? Arrays.toString(args) : ""); final Field[] _fields = Util.spSelectSql(sql, clazz); try { return jdbcTemplate.queryForObject(sql,new RowMapper<T>(){ @Override public T mapRow(ResultSet rs, int rownum) throws SQLException { T bean = null; try { bean = clazz.newInstance(); Field[] fields = _fields!=null ? _fields : clazz.getDeclaredFields(); //获取所有属性 for(Field field : fields){ if(field.getAnnotation(PmcColumn.class)==null) continue; switch(BeanUtils.getPmcColumnType(field)) { case Types.CLOB:{ BeanUtils.setter(bean, field.getName(), lobHandler.getClobAsString(rs, BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.BLOB:{ BeanUtils.setter(bean, field.getName(), lobHandler.getBlobAsBytes(rs, BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.TIMESTAMP:{ BeanUtils.setter(bean, field.getName(),rs.getTimestamp(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.DATE:{ BeanUtils.setter(bean, field.getName(),rs.getDate(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.INTEGER:{ BeanUtils.setter(bean, field.getName(),rs.getInt(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.VARCHAR:{ BeanUtils.setter(bean, field.getName(),rs.getString(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.BIGINT:{ BeanUtils.setter(bean, field.getName(),rs.getLong(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.FLOAT:{ BeanUtils.setter(bean, field.getName(),rs.getFloat(BeanUtils.getPmcColumnName(field)), field.getType()); break; } } } } catch (Exception e) { e.printStackTrace(); } return bean; } },args); } catch (EmptyResultDataAccessException e) { return null; } catch (DataAccessException e) { throw new DaoRuntimeException("----------数据库错误saveOrUpdate()------", e); } } /** * 查询列表 * @param <T> * @param sql * @param clazz * @param args * @return */ public <T> List<T> _query(String sql,final Class<T> clazz,Object...args){ printSqlInfo(sql,args!=null ? Arrays.toString(args) : ""); //打印分页语句 final Field[] _fields = Util.spSelectSql(sql, clazz); return jdbcTemplate.query(sql, args, new RowMapper<T>(){ @Override public T mapRow(ResultSet rs, int rownum) throws SQLException { T bean = null; try { bean = clazz.newInstance(); Field[] fields = _fields!=null ? _fields : clazz.getDeclaredFields(); //获取所有属性 for(Field field : fields){ if(field.getAnnotation(PmcColumn.class)==null) continue; if(BeanUtils.getPmcColumnIgnore(field)) continue; //是否忽视 switch(BeanUtils.getPmcColumnType(field)) { case Types.CLOB:{ BeanUtils.setter(bean, field.getName(), lobHandler.getClobAsString(rs, BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.BLOB:{ BeanUtils.setter(bean, field.getName(), lobHandler.getBlobAsBytes(rs, BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.TIMESTAMP:{ BeanUtils.setter(bean, field.getName(),rs.getTimestamp(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.DATE:{ BeanUtils.setter(bean, field.getName(),rs.getDate(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.INTEGER:{ BeanUtils.setter(bean, field.getName(),rs.getInt(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.VARCHAR:{ BeanUtils.setter(bean, field.getName(),rs.getString(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.BIGINT:{ BeanUtils.setter(bean, field.getName(),rs.getLong(BeanUtils.getPmcColumnName(field)), field.getType()); break; } case Types.FLOAT:{ BeanUtils.setter(bean, field.getName(),rs.getFloat(BeanUtils.getPmcColumnName(field)), field.getType()); break; } } } } catch (Exception e) { e.printStackTrace(); } return bean; } }); } /** * 添加或修改某条记录 * @param <T> * @param sql * @param bean */ public <T> void _saveOrUpdate(String sql,final T bean){ final Map<String,Integer> columnTypes = new HashMap<String,Integer>(); Map<String,String> columnMaps = new HashMap<String,String>(); Field[] fields = bean.getClass().getDeclaredFields(); //获取所有属性 for(Field field : fields){ columnTypes.put(field.getName(), BeanUtils.getPmcColumnType(field)); columnMaps.put(field.getName(), BeanUtils.getPmcColumnName(field)); } final Map<String,List<String>> resultMap = Util.spQuerysql(sql,columnMaps); if(resultMap==null) throw new PmcRuntimeException(String.format("你提供的SQL语句有问题,请详细检查再次尝试运行。SQL:[s%]",sql)); Object[] validSql = resultMap.keySet().toArray(); //改变后的Sql语句 printSqlInfo(sql+"<<----->>"+validSql[0].toString(),""); //打印改变前后的sql语句 final List<String> fieldList = resultMap.get(validSql[0]); //对应插入的bean字段 jdbcTemplate.execute(validSql[0].toString(),new AbstractLobCreatingPreparedStatementCallback(this.lobHandler) { @Override protected void setValues(PreparedStatement ps, LobCreator lobCreater) throws SQLException, DataAccessException { for(int i=0,length=fieldList.size();i<length;i++){ String filedValue = fieldList.get(i); Integer columnType = columnTypes.get(filedValue); if(columnType==null) throw new PmcRuntimeException(String.format("你提供的SQL语句有中存在不能识别的Bean属性字段,请详细检查再次尝试运行")); switch (columnType) { case Types.CLOB:{ lobCreater.setClobAsString(ps, i+1, BeanUtils.getter(bean, filedValue)==null ? null : BeanUtils.getter(bean, filedValue).toString()); break; } case Types.BLOB:{ lobCreater.setBlobAsBytes(ps, i+1, BeanUtils.getter(bean, filedValue)==null ? null : (byte[])BeanUtils.getter(bean, filedValue)); break; } case Types.TIMESTAMP:{ ps.setTimestamp(i+1, BeanUtils.getter(bean, filedValue)==null ? null : (Timestamp)BeanUtils.getter(bean, filedValue)); break; } case Types.DATE:{ ps.setDate(i+1, BeanUtils.getter(bean, filedValue)==null ? null : (Date)BeanUtils.getter(bean, filedValue)); break; } case Types.INTEGER:{ ps.setObject(i+1, BeanUtils.getter(bean, filedValue)==null ? null : (Integer)BeanUtils.getter(bean, filedValue), Types.INTEGER); break; } case Types.VARCHAR:{ ps.setString(i+1, BeanUtils.getter(bean, filedValue)==null ? null : BeanUtils.getter(bean, filedValue).toString()); break; } case Types.BIGINT:{ ps.setObject(i+1, BeanUtils.getter(bean, filedValue)==null ? null : (Long)BeanUtils.getter(bean, filedValue), Types.BIGINT); break; } case Types.FLOAT:{ ps.setObject(i+1, BeanUtils.getter(bean, filedValue)==null ? null : (Float)BeanUtils.getter(bean, filedValue), Types.FLOAT); break; } } } } }); } }
如何使用以上方法,需要注意以下2个方面:
其一:如果某个Bean类中包括Clob和Blob字段,那么该Bean的字段类型需要加入PmcColumn注解。如:
/** * @description * @author aokunsang * @date 2013-7-4 */ public class TDemo implements Serializable{ @PmcColumn(columnName="ID",type=Types.BIGINT) private Long id; @PmcColumn(columnName="NAME",type=Types.VARCHAR) private String name; @PmcColumn(columnName="DEMO_PIC",type=Types.BLOB,ignore=true) private byte[] pic; //BLOB类型,属性字段类型为byte[] @PmcColumn(columnName="CONTENT",type=Types.CLOB,ignore=true) private String content; //CLOB类型,属性字段类型为String setter and getter... }
其二:Service业务方法中注入StGenericdao类,使用其方法即可;当然如果你操作的Bean类没有Clob和Blob类型字段就无需写PmcColumn注解,注入IGenericDao接口也可以。
/** * @description * @author aokunsang * @date 2013-7-4 */ @Service public class DemoServiceImpl implements IDemoService{ @Resource(name="genericDao") private StGenericDao genericDao; public void saveDemo(TDemo demo){ genericDao._saveOrUpdate("insert into tdemo values(:id,:name,:pic,:content)",demo); } }
相关推荐
spring 中对大数据的处理,包括clob,blob的数据。比之jdbc下简便很多。
CLOB 和 BLOB 的主要区别是:CLOB 使用 CHAR 来保存数据,而 BLOB 使用二进制保存数据。CLOB 主要用于存储字符数据,而 BLOB 主要用于存储二进制数据。 在 MySQL 中,BLOB 是个类型系列,包括:TinyBlob、Blob、...
在数据库编程领域,CLOB(Character Large Object)和BLOB(Binary Large Object)是用于存储大量文本和二进制数据的数据类型。在DELPHI中,处理这些大型对象时需要特殊的技术和策略。本篇文章将深入探讨DELPHI中...
总的来说,Spring通过JDBC提供了一套完善的接口和工具类来处理CLOB和BLOB,使得开发者无需直接与JDBC API打交道,降低了数据库操作的复杂度。在实际项目中,根据业务需求,合理运用这些功能可以极大地提高开发效率和...
Mybatis 处理 CLOB、BLOB 类型数据 MyBatis 处理 CLOB、BLOB 类型数据是指在使用 MyBatis ...通过使用 MyBatis 处理 CLOB 和 BLOB 类型数据,可以方便地存储和读取大字段类型的数据,提高应用程序的性能和可扩展性。
2. **Oracle.ManagedDataAccess.dll**:这是Oracle官方提供的Managed Driver,它是一个.NET Framework库,允许开发者在.NET环境中直接访问Oracle数据库,支持Clob和Blob操作。 3. **SqlSugar.dll**:这是一个流行的...
本文将深入探讨这两个数据库系统如何处理`CLOB`(Character Large Object)和`BLOB`(Binary Large Object)字段,这两种字段类型主要用于存储大量文本或二进制数据。 `CLOB`用于存储非结构化的字符数据,如长篇...
- 可能会提到一些开发工具,如Eclipse、IntelliJ IDEA中如何配置和调试与Clob和Blob相关的代码,或者使用数据库管理工具如SQL Developer进行数据查看和操作。 7. **示例代码**: - 包含在`bigstring_oracle_src`...
在示例中,我们设置占位符的值,然后执行插入操作,将本地文件的内容写入到CLOB和BLOB字段。 在读取数据时,我们使用`ResultSet`对象来获取查询结果。对于CLOB字段,我们通过`ResultSet.getClob()`方法获取`Clob`...
Java 中处理 Clob 和 Blob 类型的注解配置 Java 中处理 Clob 和 Blob 类型的注解配置是一种常见的处理大规模数据的方法。Clob(Character Large OBject)类型和 Blob(Binary Large OBject)类型是数据库中两种常用...
了解BLOB和CLOB的区别以及如何在Oracle中进行插入和查询操作对于数据库开发者和管理员来说至关重要。 首先,我们来看BLOB和CLOB的主要区别: 1. 数据类型:BLOB用于存储二进制大对象,如图片、视频、音频文件或者...
修改clob blob 字段 修改clob blob 字段 修改clob blob 字段
对于CLOB和BLOB字段,Oracle JDBC驱动提供了`oracle.jdbc.driver.OracleClob`和`oracle.jdbc.driver.OracleBlob`类,它们实现了Java的标准接口`java.sql.Clob`和`java.sql.Blob`。这两个接口提供了读取和写入大数据...
在保存或更新带有Clob和Blob字段的实体时,Hibernate会自动处理这些数据的插入和更新操作。例如,当你调用`session.saveOrUpdate(entity)`或`entityManager.persist(entity)`时,Hibernate会将Clob和Blob的内容正确...
Oracle数据库在存储大对象(BLOB和CLOB)时提供了强大的功能,但处理这些类型的数据进行导入导出可能会带来挑战。"Oracle导出Clob,Blob工具版本2" 是一个专为解决这个问题而设计的应用程序,它改进了对CLOB...
在数据库管理中,存储非结构化数据如图片、音频或视频文件时,通常会使用`CLOB`(Character Large Object)和`BLOB`(Binary Large Object)这两种数据类型。Oracle数据库系统支持这两种数据类型,用于存储大量文本...
### Oracle中的BLOB和CLOB的区别 在Oracle数据库中,`BLOB`(Binary Large Object)和`CLOB`(Character Large Object)是用于存储大量数据的两种特殊数据类型。这两种类型都属于`LOB`(Large Object)类别,主要...
一个完整的工程,主要功能为:spring+hbernate对clob、blob字段的处理 包括:数据脚本、典型的SSH框架处理,以及spring、hibernate数据批量保存等功能源码、所用到的lib包 数据环境为:oracle 10G 开发:Mycelipse5.1...
为了将BLOB转换为CLOB,我们需要考虑数据大小和处理效率。在示例代码中,`blob_to_clob`函数首先创建了一个临时的CLOB变量`v_clob`。然后,通过`DBMS_LOB.GETLENGTH`获取BLOB的总长度,计算出需要处理的次数`tmp_num...