从数据库读取数据后利用反射为对应的实体类的属性赋值

Posted qq1913284695

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从数据库读取数据后利用反射为对应的实体类的属性赋值相关的知识,希望对你有一定的参考价值。

1、连接数据库并关闭连接(jdbctools.java)

package com.xiaojie.dao;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Jdbctools {
	private static DataSource ds=null;  
    //数据库连接池应只被初始化一次  
    static{  
        ds=new ComboPooledDataSource("helloc3p0");  
    }  
    //获取数据库连接  
    public static  Connection getConnection() throws ClassNotFoundException, SQLException, IOException{  
        return ds.getConnection();      
    } 
    public static void shifanglianjie(Connection ct, PreparedStatement ps,ResultSet rs) { 
    	if(rs!=null){
    		try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	if(ps!=null){
    		try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    	if(ct!=null){
    		try {
				ct.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }

}

2、DAO 模块

package com.xiaojie.dao;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.xiaojie.beans.Trade;

import java.sql.SQLException;
public class DAO<T> {
//查询一条记录,返回对应的对象
	public <T> T query(Class<T> clazz,String sql,Object...args){
		T example=null;
		Connection ct=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			//1、获取connection
			ct=Jdbctools.getConnection();
			System.out.println("query获取到数据库的连接了");
			//2、获取PreparedStatement
			ps=ct.prepareStatement(sql);
			//3、填充占位符
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1, args[i]);
			}
			//4、进行查询,得到ResultSet
			rs=ps.executeQuery();
			//5、准备一个Map<String,Object>:(前提是结果集中要有记录)
			if(rs.next()){
					Map<String,Object> values=new HashMap<String,Object>();
				
				//6、得到ResultSetMetaData对象
				ResultSetMetaData rsd=rs.getMetaData();
				//7、处理ResultSet,把指针向下移动一个单位
				
				//8、由ResultSetMetaData对象得到结果集中有多少列
				int lieshu=rsd.getColumnCount();
				//9、由ResultSetMetaData对象得到每一列的别名,由ResultSet得到具体每一列的值
				for(int i=0;i<lieshu;i++){
					String lieming=rsd.getColumnLabel(i+1);
					Object liezhi=rs.getObject(i+1);
					//10、填充Map对象
					values.put(lieming,liezhi);
				}
			
				
				//11、用反射创建Class对应的对象
				example=clazz.newInstance();
				//12、遍历Map对象,用反射填充对象的属性值,
				for(Map.Entry<String, Object> ent:values.entrySet()){
					String name=ent.getKey();
					Object value=ent.getValue();
					//用反射赋值
					ReflectionUtils.setFieldValue(example, name,  value);
			
				}
			}
		} catch (Exception e) {
				e.printStackTrace();
		}finally{
			Jdbctools.shifanglianjie(ct, ps, rs);
		}
		return example;
		
	}
	//查询多条记录,返回多个对应的对象
	public List<T>  querylist(Class<T> clazz,String sql,Object...args){
		T example=null;
		Connection ct=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		List li=new ArrayList();
		try {
			//1、获取connection
			ct=Jdbctools.getConnection();
			System.out.println("querylist获取到数据库的连接了");
			//2、获取PreparedStatement
			ps=ct.prepareStatement(sql);
			//3、填充占位符
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1, args[i]);
			}
			//4、进行查询,得到ResultSet
			rs=ps.executeQuery();
			//5、准备一个Map<String,Object>:(前提是结果集中要有记录)
			
			while(rs.next()){
					Map<String,Object> values=new HashMap<String,Object>();
				
				//6、得到ResultSetMetaData对象
				ResultSetMetaData rsd=rs.getMetaData();
				//7、处理ResultSet,把指针向下移动一个单位
				
				//8、由ResultSetMetaData对象得到结果集中有多少列
				int lieshu=rsd.getColumnCount();
				//9、由ResultSetMetaData对象得到每一列的别名,由ResultSet得到具体每一列的值
				for(int i=0;i<lieshu;i++){
					String lieming=rsd.getColumnLabel(i+1);
					Object liezhi=rs.getObject(i+1);
					//10、填充Map对象
					values.put(lieming,liezhi);
				}
			
				
				//11、用反射创建Class对应的对象
				example=clazz.newInstance();
				//12、遍历Map对象,用反射填充对象的属性值,
				for(Map.Entry<String, Object> ent:values.entrySet()){
					String name=ent.getKey();
					Object value=ent.getValue();
					//用反射赋值
					ReflectionUtils.setFieldValue(example, name,  value);
			
				}
				li.add(example);
			}
		} catch (Exception e) {
				e.printStackTrace();
		}finally{
			Jdbctools.shifanglianjie(ct, ps, rs);
		}
		return li;
		
	}
}


3、反射工具类

package com.xiaojie.dao;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 反射的 Utils 函数集合
 * 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数
 * @author Administrator
 *
 */
public class ReflectionUtils {

	
	/**
	 * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型
	 * 如: public EmployeeDao extends BaseDao<Employee, String>
	 * @param clazz
	 * @param index
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Class getSuperClassGenricType(Class clazz, int index){
		Type genType = clazz.getGenericSuperclass();
		
		if(!(genType instanceof ParameterizedType)){
			return Object.class;
		}
		
		Type [] params = ((ParameterizedType)genType).getActualTypeArguments();
		
		if(index >= params.length || index < 0){
			return Object.class;
		}
		
		if(!(params[index] instanceof Class)){
			return Object.class;
		}
		
		return (Class) params[index];
	}
	
	/**
	 * 通过反射, 获得 Class 定义中声明的父类的泛型参数类型
	 * 如: public EmployeeDao extends BaseDao<Employee, String>
	 * @param <T>
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static<T> Class<T> getSuperGenericType(Class clazz){
		return getSuperClassGenricType(clazz, 0);
	}
	
	/**
	 * 循环向上转型, 获取对象的 DeclaredMethod
	 * @param object
	 * @param methodName
	 * @param parameterTypes
	 * @return
	 */
	public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes){
		
		for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
			try {
				//superClass.getMethod(methodName, parameterTypes);
				return superClass.getDeclaredMethod(methodName, parameterTypes);
			} catch (NoSuchMethodException e) {
				//Method 不在当前类定义, 继续向上转型
			}
			//..
		}
		
		return null;
	}
	
	/**
	 * 使 filed 变为可访问
	 * @param field
	 */
	public static void makeAccessible(Field field){
		if(!Modifier.isPublic(field.getModifiers())){
			field.setAccessible(true);
		}
	}
	
	/**
	 * 循环向上转型, 获取对象的 DeclaredField
	 * @param object
	 * @param filedName
	 * @return
	 */
	public static Field getDeclaredField(Object object, String filedName){
		
		for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
			try {
				return superClass.getDeclaredField(filedName);
			} catch (NoSuchFieldException e) {
				//Field 不在当前类定义, 继续向上转型
			}
		}
		return null;
	}
	
	/**
	 * 直接调用对象方法, 而忽略修饰符(private, protected)
	 * @param object
	 * @param methodName
	 * @param parameterTypes
	 * @param parameters
	 * @return
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	public static Object invokeMethod(Object object, String methodName, Class<?> [] parameterTypes,
			Object [] parameters) throws InvocationTargetException{
		
		Method method = getDeclaredMethod(object, methodName, parameterTypes);
		
		if(method == null){
			throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
		}
		
		method.setAccessible(true);
		
		try {
			return method.invoke(object, parameters);
		} catch(IllegalAccessException e) {
			System.out.println("不可能抛出的异常");
		} 
		
		return null;
	}
	
	/**
	 * 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
	 * @param object
	 * @param fieldName
	 * @param value
	 */
	public static void setFieldValue(Object object, String fieldName, Object value){
		Field field = getDeclaredField(object, fieldName);
		
		if (field == null)
			throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
		
		makeAccessible(field);
		
		try {
			field.set(object, value);
		} catch (IllegalAccessException e) {
			System.out.println("不可能抛出的异常");
		}
	}
	
	/**
	 * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
	 * @param object
	 * @param fieldName
	 * @return
	 */
	public static Object getFieldValue(Object object, String fieldName){
		Field field = getDeclaredField(object, fieldName);
		
		if (field == null)
			throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
		
		makeAccessible(field);
		
		Object result = null;
		
		try {
			result = field.get(object);
		} catch (IllegalAccessException e) {
			System.out.println("不可能抛出的异常");
		}
		
		return result;
	}
}

4、数据库对应的那个Javabeans实体类

package com.xiaojie.beans;

import java.util.Date;

public class Trade {
	private int tradeid;
	private int userid;
	private Date tradetime;
	public int getTradeid() {
		return tradeid;
	}
	public void setTradeid(int tradeid) {
		this.tradeid = tradeid;
	}
	public int getUserid() {
		return userid;
	}
	public void setUserid(int userid) {
		this.userid = userid;
	}
	public Date getTradetime() {
		return tradetime;
	}
	public void setTradetime(Date tradetime) {
		this.tradetime = tradetime;
	}
	public Trade(int tradeid, int userid, Date tradetime) {
		super();
		this.tradeid = tradeid;
		this.userid = userid;
		this.tradetime = tradetime;
	}
	public Trade() {
		super();
	}
	
}

5、写了一个测试类试一下效果(前提是该导入的jar包都导入了,而且数据库建有相应的Javabeans的表,c3p0配置文件等都弄好了)

package com.xiaojie.test;

import java.io.IOException;
import java.sql.Date;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.xiaojie.beans.Trade;
import com.xiaojie.dao.DAO;

public class Daotest {
	private DAO dao=new DAO();
<span style="white-space:pre">	</span>//以下测试方法是测试从数据库查询一条记录给相应的Javabean的属性赋值,并在控制台显示出一条打印结果
	@Test
	public void testquery() throws ClassNotFoundException, SQLException, IOException{
		String sql="select * from trade where tradeid=?";
		Trade trade=new Trade();
		trade= (Trade) dao.query(Trade.class,sql,1);
		System.out.println("tradeid:"+trade.getTradeid()+"\nuserid:"+trade.getUserid()+"\ntradetiem:"+trade.getTradetime());
		
	}
	//以下测试方法是从数据库查询后的结果(不只一条记录)给相应的Javabean的属性赋值,并在控制台显示出多条打印结果
	@Test
	public void testquerylist(){
		String sql="select * from trade";
		Trade trade=new Trade();
		
		List<Trade>trades=new ArrayList<Trade>();
		trades=(List<Trade>) dao.querylist(Trade.class,sql);
		for(Trade trade1:trades){
			
			System.out.println("tradeid:"+trade1.getTradeid()+"\nuserid:"+trade1.getUserid()+"\ntradetiem:"+trade1.getTradetime());
		}
		
	}
}




以上是关于从数据库读取数据后利用反射为对应的实体类的属性赋值的主要内容,如果未能解决你的问题,请参考以下文章

JAVA从数据库查出来的数据放到实体类想用反射的方法给他们赋值,怎么做?

Java -- JDBC_利用反射及 JDBC 元数据编写通用的查询方法

C#用反射实现两个类的对象之间相同属性的值的复制

使用反射将DataTable的数据转成实体类

利用Java反射实现两个具有相同属性bean赋值

利用反射将IDataReader读取到实体类中效率低下的解决办法