问题:
在项目中,我们常常会实现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;
}
分享到:
相关推荐
Microsoft SQL Server 2008 Native Client (SQL Server Native Client) 是单一动态链接库 (DLL),其中包含 SQL OLE DB 提供者和 SQL ODBC 驱动程序。此链接库针对使用机器码 API (ODBC、OLE DB 和 ADO) 的应用程序...
SQL Server Native Client是微软开发的一款专门用于连接Microsoft SQL Server数据库的客户端库,它结合了ODBC(Open Database Connectivity)和OLE DB(Object Linking and Embedding, Database)接口的功能,为应用...
SQL Server Native Client是微软开发的一款专门用于与SQL Server交互的客户端库,支持多种数据库访问接口,包括ODBC(Open Database Connectivity)和OLE DB(Object Linking and Embedding, Database)。...
执行查询后,`ExecuteReader`方法返回一个`SqlDataReader`对象,该对象可以按强类型的方式读取数据库结果集中的每一行数据。 **四、强类型与数据库操作** 在ADO.NET中,强类型体现在与数据库交互时对数据的处理上...
**LINQ to Datasets:通过LINQ访问强类型数据集** LINQ(Language Integrated Query,语言集成查询)是.NET框架中的一个创新特性,它为在各种数据源上执行查询提供了统一且直观的方式。LINQ to Datasets是LINQ的一...
MyBatisPlus 自定义sql语句的实现 MyBatisPlus 是一个基于 MyBatis 的增强型 ORM 框架,它提供了强大的 CRUD 操作和条件构造器,但是在某些情况下,我们需要自定义 sql 语句来满足业务需求。本文将详细介绍如何在 ...
然而,在JPA 2.0中,使用entityManager.createNativeQuery()执行原生的SQL语句时,query.getResultList()返回的是一个List[]>,每行数据被作为一个对象数组返回。这使得代码不容易让人理解,且不灵活。因此,本文将...
强大的脚本编辑器支持自定义快捷键和代码折叠,让用户可以高效地编写和运行SQL脚本。 8. **导入导出工具** 支持多种格式的数据导入导出,如CSV、XML、Excel等,便于数据迁移和分析。 9. **安全与权限管理** ...
SQL(Structured Query Language)是用于管理和处理关系数据库的标准编程语言,它在数据查询、更新、插入和删除等方面具有广泛的应用。对于新手来说,熟练掌握SQL是进入数据分析、数据库管理等领域的重要一步。"SQL...
【标题】:“强类型面向对象动态SQL生成器的设计与实现” 【描述】:本文介绍了一种在Java开发环境中,利用SQL与关系数据库交互的工具,它基于JDBC和SQL,不依赖具体数据库,通过强类型高级面向对象语言特性,提高...
3. **动态构建**:由于Go语言的强类型特性,Go-SQLBuilder可以根据不同的条件或循环结构动态生成SQL,这在处理复杂查询逻辑时非常有用。 4. **支持多种操作**:除了基本的SELECT、INSERT、UPDATE和DELETE语句外,Go...
T-SQL强化RAISERROR详解,SQL 注入,使用 OUTPUT 游标参数,使用 WITH RECOMPILE 选项,使用sp_addmessage添加自定义消息 京华志&精华志出品 希望大家互相学习,互相进步 支持CSDN 支持微软 主要包括C# ASP.NET SQLDBA ...
LINQ(Language Integrated Query,语言集成查询)是.NET Framework 3.5引入的一个重要特性,它的目标是将查询表达式直接整合到编程语言中,提供了强类型、类型安全和编译时检查的查询能力。 在LINQ to SQL中,...
NQuery是一款专为处理XML文件而设计的数据库接口,它提供了类似于SQL的查询语言,使得开发者可以方便地对XML数据进行检索、操作和管理。在本文中,我们将深入探讨NQuery的基本概念、功能特性以及如何使用它来处理XML...
"SConfig.ini"是配置文件,可能包含了安装过程中的自定义设置选项,例如安装类型、组件选择、服务账户等信息。 7. **管理工具**:虽然未在文件名列表中列出,但SQL Server 2008 R2通常会包含Management Studio,这...
5. **存储过程与LINQ to SQL的结合**:LINQ to SQL也支持与存储过程的交互,你可以调用存储过程并获取返回结果,同样享受强类型和调试支持。 通过LINQ to SQL,开发者可以更加专注于业务逻辑,而不必过多地关注数据...
sqljdbc41.jar属于类型4,即Direct (Native API) Driver,它通过TCP/IP协议直接与SQLServer通信,提高了效率和性能。 三、sqljdbc41.jar的工作原理 当Java应用程序加载sqljdbc41.jar并建立与SQLServer的连接时,它...
SQL Compare Pro 比较和同步SQL Server数据库结构 SQL Data Compare Pro 比较和同步SQL Server...SQL Object Level Recovery Native 从SQL Server备份恢复数据库对象 SQL Search 在SQL Server数据库结构中搜索
Oracle数据库是世界上最流行的数据库管理系统之一,SQL(Structured Query Language)是用于管理关系数据库的标准语言,而PL/SQL是Oracle数据库特有的编程语言,扩展了SQL的功能,使得能够编写复杂的存储过程和...
SQL Compare Pro 比较和同步SQL Server数据库结构 SQL Data Compare Pro 比较和同步SQL Server...SQL Object Level Recovery Native 从SQL Server备份恢复数据库对象 SQL Search 在SQL Server数据库结构中搜索