`
xiechangming
  • 浏览: 26626 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

自定义的Native SQL Query返回强类型的Bean

阅读更多

问题:

在项目中,我们常常会实现Report功能,通常使用Native SQL Query返回查询的数据集,而这些数据集是Raw typed,Query的调用者获得这些原始的数据集后需要显示地将其转化成强类型的Java Bean类,如何减少这些繁琐的转换呢?

 

解决方案:

将原始数据集的每条记录根据一定的规则将其自动映射成Java Bean 对象,比如为Query 返回的列名在Java Bean类中查找匹配的字段(忽略_,空格,大小写,等), 使用反射将该列的值赋值到Java Bean的字段中。

 

Spring 中为我们提供了一个现成的类用来实现此功能的类-BeanPropertyRowMapper,该类就是使用反射依据列名在Java Bean类中查找匹配的属性,如下是其核心代码片段:

public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
		Assert.state(this.mappedClass != null, "Mapped class was not specified");
		T mappedObject = BeanUtils.instantiate(this.mappedClass);
		BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
		initBeanWrapper(bw);

		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<String>() : null);

		for (int index = 1; index <= columnCount; index++) {
			String column = JdbcUtils.lookupColumnName(rsmd, index);
			PropertyDescriptor pd = this.mappedFields.get(column.replaceAll(" ", "").toLowerCase());
			if (pd != null) {
				try {
					Object value = getColumnValue(rs, index, pd);
					if (logger.isDebugEnabled() && rowNumber == 0) {
						logger.debug("Mapping column '" + column + "' to property '" +
								pd.getName() + "' of type " + pd.getPropertyType());
					}
					try {
						bw.setPropertyValue(pd.getName(), value);
					}
					catch (TypeMismatchException e) {
						if (value == null && primitivesDefaultedForNullValue) {
							logger.debug("Intercepted TypeMismatchException for row " + rowNumber +
									" and column '" + column + "' with value " + value +
									" when setting property '" + pd.getName() + "' of type " + pd.getPropertyType() +
									" on object: " + mappedObject);
						}
						else {
							throw e;
						}
					}
					if (populatedProperties != null) {
						populatedProperties.add(pd.getName());
					}
				}
				catch (NotWritablePropertyException ex) {
					throw new DataRetrievalFailureException(
							"Unable to map column " + column + " to property " + pd.getName(), ex);
				}
			}
		}

		if (populatedProperties != null && !populatedProperties.equals(this.mappedProperties)) {
			throw new InvalidDataAccessApiUsageException("Given ResultSet does not contain all fields " +
					"necessary to populate object of class [" + this.mappedClass + "]: " + this.mappedProperties);
		}

		return mappedObject;
	}

 

从上面可以看出 其输入的数据源,只是指出ResultSet,如过需要支持其他的数据源,则得自己实现了。如下为我自己实现的一个例子,输入源为CursoredStream(EclipseLink):

public T mapRow(CursoredStream cs) {

		DatabaseRecord row = (DatabaseRecord) cs.next();

		List<DatabaseField> fields = cs.getFields();

		Assert.state(this.mappedClass != null, "Mapped class was not specified");
		T mappedObject = BeanUtils.instantiate(this.mappedClass);
		BeanWrapper bw = PropertyAccessorFactory
				.forBeanPropertyAccess(mappedObject);
		initBeanWrapper(bw);

		// ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = fields.size();

		Set<String> populatedProperties = (isCheckFullyPopulated() ? new HashSet<String>()
				: null);

		for (DatabaseField field : fields) {
			String columnName = field.getName();// JdbcUtils.lookupColumnName(rsmd,
												// index);
			PropertyDescriptor pd = this.mappedFields.get(columnName
					.replaceAll(" ", "").toLowerCase());
			if (pd != null) {
				try {
					Object value = getColumnValue(row, field, pd);

					try {
						bw.setPropertyValue(pd.getName(), value);
					} catch (TypeMismatchException e) {
						if (value == null && primitivesDefaultedForNullValue) {
							logger.debug("Intercepted TypeMismatchException for row "
									+ cs.getPosition()
									+ " and column '"
									+ columnName
									+ "' with value "
									+ value
									+ " when setting property '"
									+ pd.getName()
									+ "' of type "
									+ pd.getPropertyType()
									+ " on object: " + mappedObject);
						} else {
							throw e;
						}
					}
					if (populatedProperties != null) {
						populatedProperties.add(pd.getName());
					}
				} catch (NotWritablePropertyException ex) {
					throw new DataRetrievalFailureException(
							"Unable to map column " + columnName
									+ " to property " + pd.getName(), ex);
				}
			}
		}

		if (populatedProperties != null
				&& !populatedProperties.equals(this.mappedProperties)) {
			throw new InvalidDataAccessApiUsageException(
					"Given ResultSet does not contain all fields "
							+ "necessary to populate object of class ["
							+ this.mappedClass + "]: " + this.mappedProperties);
		}

		return mappedObject;
	}

 

 

分享到:
评论

相关推荐

    SQL Server Native Client大全(官网下载整理9,10,11)

    SQL Server Native Client是微软开发的一款专门用于连接Microsoft SQL Server数据库的客户端库,它结合了ODBC(Open Database Connectivity)和OLE DB(Object Linking and Embedding, Database)接口的功能,为应用...

    SqlServerQueryVisualizer

    **SqlServerQueryVisualizer详解** Sql Server Query Visualizer是一款强大的可视化工具,专为Linq to SQL开发者设计,旨在帮助他们更直观地理解并调试查询。它提供了对查询执行过程的洞察,使得开发人员能够有效地...

    强类型_强类型_

    执行查询后,`ExecuteReader`方法返回一个`SqlDataReader`对象,该对象可以按强类型的方式读取数据库结果集中的每一行数据。 **四、强类型与数据库操作** 在ADO.NET中,强类型体现在与数据库交互时对数据的处理上...

    MyBatisPlus 自定义sql语句的实现

    MyBatisPlus 自定义sql语句的实现 MyBatisPlus 是一个基于 MyBatis 的增强型 ORM 框架,它提供了强大的 CRUD 操作和条件构造器,但是在某些情况下,我们需要自定义 sql 语句来满足业务需求。本文将详细介绍如何在 ...

    5.5游标强类型弱类型异常报错.sql

    5.5游标强类型弱类型异常报错.sql

    SQL强化练习工具

    SQL(Structured Query Language)是用于管理和处理关系数据库的标准编程语言,它在数据查询、更新、插入和删除等方面具有广泛的应用。对于新手来说,熟练掌握SQL是进入数据分析、数据库管理等领域的重要一步。"SQL...

    强类型面向对象动态SQL生成器的设计与实现.pdf

    【标题】:“强类型面向对象动态SQL生成器的设计与实现” 【描述】:本文介绍了一种在Java开发环境中,利用SQL与关系数据库交互的工具,它基于JDBC和SQL,不依赖具体数据库,通过强类型高级面向对象语言特性,提高...

    T-SQL强化RAISERROR详解,SQL 注入,使用 OUTPUT 游标参数,使用 WITH RECOMPILE 选项,使用sp_addmessage添加自定义消息

    T-SQL强化RAISERROR详解,SQL 注入,使用 OUTPUT 游标参数,使用 WITH RECOMPILE 选项,使用sp_addmessage添加自定义消息 京华志&精华志出品 希望大家互相学习,互相进步 支持CSDN 支持微软 主要包括C# ASP.NET SQLDBA ...

    c#linq to sql

    LINQ(Language Integrated Query,语言集成查询)是.NET Framework 3.5引入的一个重要特性,它的目标是将查询表达式直接整合到编程语言中,提供了强类型、类型安全和编译时检查的查询能力。 在LINQ to SQL中,...

    NQuery(基于XML文件的数据库接口)

    NQuery是一款专为处理XML文件而设计的数据库接口,它提供了类似于SQL的查询语言,使得开发者可以方便地对XML数据进行检索、操作和管理。在本文中,我们将深入探讨NQuery的基本概念、功能特性以及如何使用它来处理XML...

    Go-Go-SQLBuilder是一个用于创建SQL语句的工具函数库

    3. **动态构建**:由于Go语言的强类型特性,Go-SQLBuilder可以根据不同的条件或循环结构动态生成SQL,这在处理复杂查询逻辑时非常有用。 4. **支持多种操作**:除了基本的SELECT、INSERT、UPDATE和DELETE语句外,Go...

    LINQ to SQL.pdf

    5. **存储过程与LINQ to SQL的结合**:LINQ to SQL也支持与存储过程的交互,你可以调用存储过程并获取返回结果,同样享受强类型和调试支持。 通过LINQ to SQL,开发者可以更加专注于业务逻辑,而不必过多地关注数据...

    SQL ToolBelt 2018最新版 分卷1

    SQL Compare Pro  比较和同步SQL Server数据库结构 SQL Data Compare Pro  比较和同步SQL Server...SQL Object Level Recovery Native 从SQL Server备份恢复数据库对象 SQL Search  在SQL Server数据库结构中搜索

    Oralce数据库SQL和pl_sql实例教程

    Oracle数据库是世界上最流行的数据库管理系统之一,SQL(Structured Query Language)是用于管理关系数据库的标准语言,而PL/SQL是Oracle数据库特有的编程语言,扩展了SQL的功能,使得能够编写复杂的存储过程和...

    自定义多类型进度条

    在Android开发中,进度条...总之,自定义多类型进度条是Android开发中的一个实践性强、灵活性高的课题。通过理解并掌握上述知识点,开发者可以创造出富有创意且符合应用需求的进度条组件,提升应用的用户体验。

    SQL ToolBelt 2018最新版 分卷2

    SQL Compare Pro  比较和同步SQL Server数据库结构 SQL Data Compare Pro  比较和同步SQL Server...SQL Object Level Recovery Native 从SQL Server备份恢复数据库对象 SQL Search  在SQL Server数据库结构中搜索

    Red Gate SQL Toolbelt 1.8.2.108_Keygen

    最新的Red Gate SQL Toolbelt 1.8.2.108 完整开发套件的Key 你懂的 亲测可用 SQL Toolbelt允许开发人员...SQL Object Level Recovery Native 从SQL Server备份恢复数据库对象 SQL Search 在SQL Server数据库架构中搜索

    佰思超强自定义调查投票系统 v5.9.rar

    可自定义题目类型 (如单选 多选,单选 文字,纯文字,文字 列表等等类型),同时可自由组合各种新类型题目 可自定义制作生成绝大多数报名表 可自定义制作生成绝大多数问卷调查,图片调查等 可自定义制作生成绝大...

    超强自定义调查投票系统 v2.2.2

    调查投票系统介绍:可生成网上可见的多数调查系统投票系统,支持同时产生多套调查投票,可自定义题目类型(如单选+多选,单选+文字,纯文字等类型)可自由更换界面,使用时提交和提交成功界面均是纯Html格式。...

Global site tag (gtag.js) - Google Analytics