`
aokunsang
  • 浏览: 816419 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

SpringJdbcTemplate操作Clob和Blob的通用类封装

 
阅读更多

        项目中使用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的jdbcTemplate处理blob、clob

    spring 中对大数据的处理,包括clob,blob的数据。比之jdbc下简便很多。

    CLOB、BLOB___CLOB与BLOB的区别

    CLOB 和 BLOB 的主要区别是:CLOB 使用 CHAR 来保存数据,而 BLOB 使用二进制保存数据。CLOB 主要用于存储字符数据,而 BLOB 主要用于存储二进制数据。 在 MySQL 中,BLOB 是个类型系列,包括:TinyBlob、Blob、...

    DELPHI的CLOB和BLOB存取处理.zip_DELPHI的CLOB和BLOB存取处理_hallzgz

    在数据库编程领域,CLOB(Character Large Object)和BLOB(Binary Large Object)是用于存储大量文本和二进制数据的数据类型。在DELPHI中,处理这些大型对象时需要特殊的技术和策略。本篇文章将深入探讨DELPHI中...

    spring2通过jdbc的方式读取、更新数据库的clob或者blob类型的数据

    总的来说,Spring通过JDBC提供了一套完善的接口和工具类来处理CLOB和BLOB,使得开发者无需直接与JDBC API打交道,降低了数据库操作的复杂度。在实际项目中,根据业务需求,合理运用这些功能可以极大地提高开发效率和...

    Mybatis 处理 CLOB、BLOB 类型数据

    Mybatis 处理 CLOB、BLOB 类型数据 MyBatis 处理 CLOB、BLOB 类型数据是指在使用 MyBatis ...通过使用 MyBatis 处理 CLOB 和 BLOB 类型数据,可以方便地存储和读取大字段类型的数据,提高应用程序的性能和可扩展性。

    Oracle导出Clob,Blob工具

    2. **Oracle.ManagedDataAccess.dll**:这是Oracle官方提供的Managed Driver,它是一个.NET Framework库,允许开发者在.NET环境中直接访问Oracle数据库,支持Clob和Blob操作。 3. **SqlSugar.dll**:这是一个流行的...

    mysql和Oracle在对clob和blob字段的处理

    本文将深入探讨这两个数据库系统如何处理`CLOB`(Character Large Object)和`BLOB`(Binary Large Object)字段,这两种字段类型主要用于存储大量文本或二进制数据。 `CLOB`用于存储非结构化的字符数据,如长篇...

    Hibernate操作Oarcle中Clob、Blob字段小结

    - 可能会提到一些开发工具,如Eclipse、IntelliJ IDEA中如何配置和调试与Clob和Blob相关的代码,或者使用数据库管理工具如SQL Developer进行数据查看和操作。 7. **示例代码**: - 包含在`bigstring_oracle_src`...

    Oracle clob和blob在jdbc的应用

    在示例中,我们设置占位符的值,然后执行插入操作,将本地文件的内容写入到CLOB和BLOB字段。 在读取数据时,我们使用`ResultSet`对象来获取查询结果。对于CLOB字段,我们通过`ResultSet.getClob()`方法获取`Clob`...

    java中(注解符)处理Clob(blob)类型

    Java 中处理 Clob 和 Blob 类型的注解配置 Java 中处理 Clob 和 Blob 类型的注解配置是一种常见的处理大规模数据的方法。Clob(Character Large OBject)类型和 Blob(Binary Large OBject)类型是数据库中两种常用...

    BLOB和CLOB的区别以及在ORALCE中的插入和查询操作

    了解BLOB和CLOB的区别以及如何在Oracle中进行插入和查询操作对于数据库开发者和管理员来说至关重要。 首先,我们来看BLOB和CLOB的主要区别: 1. 数据类型:BLOB用于存储二进制大对象,如图片、视频、音频文件或者...

    修改clob blob 字段

    修改clob blob 字段 修改clob blob 字段 修改clob blob 字段

    clob-blob.rar_blob and clob_clob_java CLOB_java oracle cl_oracle

    对于CLOB和BLOB字段,Oracle JDBC驱动提供了`oracle.jdbc.driver.OracleClob`和`oracle.jdbc.driver.OracleBlob`类,它们实现了Java的标准接口`java.sql.Clob`和`java.sql.Blob`。这两个接口提供了读取和写入大数据...

    关于在Hibernate中对于Clob,Blob字段的处理方法

    在保存或更新带有Clob和Blob字段的实体时,Hibernate会自动处理这些数据的插入和更新操作。例如,当你调用`session.saveOrUpdate(entity)`或`entityManager.persist(entity)`时,Hibernate会将Clob和Blob的内容正确...

    Oracle导出Clob,Blob工具版本2

    Oracle数据库在存储大对象(BLOB和CLOB)时提供了强大的功能,但处理这些类型的数据进行导入导出可能会带来挑战。"Oracle导出Clob,Blob工具版本2" 是一个专为解决这个问题而设计的应用程序,它改进了对CLOB...

    图片存入Oracle中,用clob和blob两种方式

    在数据库管理中,存储非结构化数据如图片、音频或视频文件时,通常会使用`CLOB`(Character Large Object)和`BLOB`(Binary Large Object)这两种数据类型。Oracle数据库系统支持这两种数据类型,用于存储大量文本...

    oracle中的Blob和Clob区别

    ### Oracle中的BLOB和CLOB的区别 在Oracle数据库中,`BLOB`(Binary Large Object)和`CLOB`(Character Large Object)是用于存储大量数据的两种特殊数据类型。这两种类型都属于`LOB`(Large Object)类别,主要...

    spring+hbernate对clob、blob字段的处理

    一个完整的工程,主要功能为:spring+hbernate对clob、blob字段的处理 包括:数据脚本、典型的SSH框架处理,以及spring、hibernate数据批量保存等功能源码、所用到的lib包 数据环境为:oracle 10G 开发:Mycelipse5.1...

    oracle(blob转换为clob)

    为了将BLOB转换为CLOB,我们需要考虑数据大小和处理效率。在示例代码中,`blob_to_clob`函数首先创建了一个临时的CLOB变量`v_clob`。然后,通过`DBMS_LOB.GETLENGTH`获取BLOB的总长度,计算出需要处理的次数`tmp_num...

Global site tag (gtag.js) - Google Analytics