使用注释将JDBC ResultSet映射到对象

使用注释将JDBC ResultSet映射到对象


使用Annotations以通用方式将JDBC ResultSet映射到Object的简单代码

介绍

本技巧演示了如何使用Annotations将JDBC ResultSet映射到Object

背景 

本技巧使用Annotations和Reflection。所以这些基础知识将有所帮助。 

使用代码  

首先,我们需要一个带注释的POJO(Plain Old Java Object)来保存在ResultSet中检索的值

属性名称可以是任何内容,注释“column”指定SQL列名称。需要注释“Entity”来标记能够保存数据库值的类

下面是SamplePojo.java

隐藏   收缩    复制代码

import javax.persistence.Column;
import javax.persistence.Entity;

@Entity
public class SamplePojo {
	@Column(name="User_Id")
	private int id;
	@Column(name="User_Name")
	private String name;
	@Column(name="Address")
	private String address;
	@Column(name="Gender")
	private boolean gender;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public boolean isGender() {
		return gender;
	}
	public void setGender(boolean gender) {
		this.gender = gender;
	}
	
	@Override
	public String toString() {
		return 	"id: " + id + "\n" + 
				"name: " + name + "\n"+
				"address: " + address + "\n" +
				"gender: " + (gender ? "Male" : "Female") + "\n\n";
	}
}

将ResultSet映射到Object的代码 - ResultSetMapper.java

 下面是将ResultSet映射到此SamplePojo的Object并返回包含SamplePojo对象的ArrayList的代码  

隐藏   收缩    复制代码

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;

import org.apache.commons.beanutils.BeanUtils;

public class ResultSetMapper<T> {
	@SuppressWarnings("unchecked")
	public List<T> mapRersultSetToObject(ResultSet rs, Class outputClass) {
		List<T> outputList = null;
		try {
			// make sure resultset is not null
			if (rs != null) {
				// check if outputClass has 'Entity' annotation
				if (outputClass.isAnnotationPresent(Entity.class)) {
					// get the resultset metadata
					ResultSetMetaData rsmd = rs.getMetaData();
					// get all the attributes of outputClass
					Field[] fields = outputClass.getDeclaredFields();
					while (rs.next()) {
						T bean = (T) outputClass.newInstance();
						for (int _iterator = 0; _iterator < rsmd
								.getColumnCount(); _iterator++) {
							// getting the SQL column name
							String columnName = rsmd
									.getColumnName(_iterator + 1);
							// reading the value of the SQL column
							Object columnValue = rs.getObject(_iterator + 1);
							// iterating over outputClass attributes to check if any attribute has 'Column' annotation with matching 'name' value
							for (Field field : fields) {
								if (field.isAnnotationPresent(Column.class)) {
									Column column = field
											.getAnnotation(Column.class);
									if (column.name().equalsIgnoreCase(
											columnName)
											&& columnValue != null) {
										BeanUtils.setProperty(bean, field
												.getName(), columnValue);
										break;
									}
								}
							}
						}
						if (outputList == null) {
							outputList = new ArrayList<T>();
						}
						outputList.add(bean);
					}

				} else {
					// throw some error
				}
			} else {
				return null;
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return outputList;
	}
}

函数mapRersultSetToObject将resultset映射到SamplePojo类型的ArrayList。它首先检查outputClass是否具有'Entity'注释。该函数的核心逻辑是,它获取outputClass中具有注释“Column”的属性。如果此属性具有“列”注释,其“name”值与SQL列名称相同,则SQL列的值将设置为outputClass中的当前属性。

使用ResultSetMapper类 

隐藏   收缩    复制代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class SampleMain {
	public static void main(String ...args){

	try {
		ResultSetMapper<SamplePojo> resultSetMapper = new ResultSetMapper<SamplePojo>();
		ResultSet resultSet = null;
		// simple JDBC code to run SQL query and populate resultSet - START
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		String database = "jdbc:odbc:AkDb"; 
		Connection connection = DriverManager.getConnection( database ,"","");
		PreparedStatement statement = connection.prepareStatement("SELECT * FROM UsersSample");
		resultSet = statement.executeQuery();
		// simple JDBC code to run SQL query and populate resultSet - END
		List<SamplePojo> pojoList = resultSetMapper.mapRersultSetToObject(resultSet, SamplePojo.class);
		// print out the list retrieved from database
		if(pojoList != null){
			for(SamplePojo pojo : pojoList){
				System.out.println(pojo);
			}
		}else{
			System.out.println("ResultSet is empty. Please check if database table is empty");
		}
		connection.close();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	} catch (SQLException e) {
		e.printStackTrace();
	}
	
	}
}

兴趣点 

不使用任何框架(ibatis / hibernate等),可以避免从ResultSet映射单个列的痛苦。如果要映射更多列,只需向POJO添加更多属性,使用正确的列名称对它们进行注释即可完成!

 如果查询很复杂,可能非常复杂,包含很多列的大量连接,只需使用SQL别名重命名每个列的唯一名称,并在注释POJO时使用此列别名

请随时分享您的意见,补充或投诉。

猜你喜欢

转载自blog.csdn.net/kingmax54212008/article/details/82746370