MyBatis封装简单的CRUD
jopen
11年前
MyBatis封装简单的CRUD
1)公共的Dao接口
import java.io.Serializable; import java.util.List; public interface IBaseDao<T extends BaseDO<T>, PK extends Serializable> { /** * 新增(不会将序列生成的ID,注入) * 效率较save(T t)高 * @param t */ void create(T t); /** * 批量新增(不会将序列生成的ID,注入) * 效率较saveOfBatch(List<T> tList)高 * @param tList */ void createOfBatch(List<T> tList); /** * 新增(会将序列生成的ID,注入) * @param t */ void save(T t); /** * 批量新增(会将序列生成的ID,注入) * @param tList */ void saveOfBatch(List<T> tList); /** * 根据ID进行删除 * @param id */ void removeById(PK id); /** * 根据ids进行批量删除 * @param ids */ void removeOfBatch(List<PK> ids); void removeAll(); /** * 更新,字段为空,则不进行更新 * @param t */ void modify(T t); /** * 批量更新 * @param tList */ void modifyOfBatch(List<T> tList); /** * 根据ID获取对象 * @param id * @return */ T findOneById(PK id); /** * 获取所有的对象 * @return */ List<T> findAll(); /** * 获取记录数 * @return */ Long findAllCount(); }
2)公共的Dao接口实现类
import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.commons.lang.StringUtils; import org.mybatis.spring.SqlSessionTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import com.msd.ass.commons.util.GenericsUtils; import com.msd.ass.commons.util.ReflectionUtils; import com.msd.ass.core.anno.base.Ignore; import com.msd.ass.core.anno.base.PrimaryKey; import com.msd.ass.core.anno.base.Table; import com.msd.ass.core.anno.base.TableColumn; import com.msd.ass.core.constant.AssConstant; @Repository("BaseDao") public abstract class BaseDao<T extends BaseDO<T>, PK extends Serializable> implements IBaseDao<T, PK> { protected Logger logger = LoggerFactory .getLogger(this .getClass()); @Resource(name = "sqlSessionTemplateASS") public SqlSessionTemplate sqlSessionTemplateASS; private Class<T> entityClass; //实体类主键名称 private String pkName; //实体类ID字段名称 private String idName; //主键的序列 private String seq; private String tableName; /** * 作cache 结构{T类的镜像,{数据库列名,实体字段名}} */ private static final Map<Class<?>, Map<String, String>> classFieldMap = new HashMap<Class<?>, Map<String, String>>(); private Map<String, String> currentColumnFieldNames; private SQLGenerator<T> sqlGenerator; /** * */ @SuppressWarnings("unchecked") public BaseDao() { super(); this.entityClass = (Class<T>) GenericsUtils .getSuperClassGenricType(this.getClass()); currentColumnFieldNames = classFieldMap.get(entityClass); if (null == currentColumnFieldNames) { currentColumnFieldNames = new LinkedHashMap<String, String>(); classFieldMap.put(entityClass, currentColumnFieldNames); } // 作cache Field[] fields = this.entityClass.getDeclaredFields(); String fieldName = null; String columnName = null; for (Field field : fields) { if (field.isAnnotationPresent(Ignore.class)) { continue; } fieldName = field.getName(); TableColumn tableColumn = field.getAnnotation(TableColumn.class); if (null != tableColumn) { columnName = tableColumn.value(); } else { columnName = null; } // 如果未标识特殊的列名,默认取字段名 columnName = (StringUtils.isEmpty(columnName) ? StringUtils .upperCase(fieldName) : columnName); currentColumnFieldNames.put(columnName, fieldName); if (field.isAnnotationPresent(PrimaryKey.class)) { // 取得ID的列名 idName = fieldName; pkName = columnName; PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class); seq = primaryKey.seq(); } } Table table = this.entityClass.getAnnotation(Table.class); if (null == table) { throw new RuntimeException("类-" + this.entityClass + ",未用@Table注解标识!!"); } tableName = table.value(); sqlGenerator = new SQLGenerator<T>(currentColumnFieldNames.keySet(), tableName,pkName,seq); } @Override public void create(T t) { sqlSessionTemplateASS.insert("create", sqlGenerator.sql_create(t, currentColumnFieldNames)); } @Override public void createOfBatch(List<T> tList) { if(null == tList || tList.isEmpty()){ return; } int len = tList.size(), i = 0; List<T> temp = new ArrayList<T>(); //获取列表的第一个对象的pk的value Object pkVal = null; for (; i < len; i++) { T t = tList.get(i); if(i==0){ pkVal = ReflectionUtils.invokeGetterMethod(t, idName); } temp.add(t); if (i > 0 && i % AssConstant.FLUSH_CRITICAL_VAL == 0) { sqlSessionTemplateASS.insert("createOfBatch", sqlGenerator .sql_createOfBatch(temp, currentColumnFieldNames,pkVal)); sqlSessionTemplateASS.flushStatements(); temp = new ArrayList<T>(); } } sqlSessionTemplateASS.insert("createOfBatch", sqlGenerator .sql_createOfBatch(temp, currentColumnFieldNames,pkVal)); } @Override public void save(T t) { if(StringUtils.isEmpty(seq)){ this.create(t); } logger.info("生成序列开始:----------start----------"); Long nextval = sqlSessionTemplateASS.selectOne("fetchSeqNextval","SELECT ".concat(seq).concat(" FROM DUAL")); ReflectionUtils.invokeSetterMethod(t, idName, nextval); logger.info("生成序列结束:---------- end ----------"); this.create(t); } @Override public void saveOfBatch(List<T> tList) { if(null == tList || tList.isEmpty()){ return; } if(StringUtils.isEmpty(seq)){ this.createOfBatch(tList); } logger.info("生成序列开始:----------start----------"); for(T t : tList){ Long nextval = sqlSessionTemplateASS.selectOne("fetchSeqNextval","SELECT ".concat(seq).concat(" FROM DUAL")); ReflectionUtils.invokeSetterMethod(t, idName, nextval); } logger.info("生成序列结束:---------- end ----------"); this.createOfBatch(tList); } @Override public void removeById(PK id) { sqlSessionTemplateASS.delete("removeById", sqlGenerator.sql_removeById(id)); } @Override public void removeOfBatch(List<PK> ids) { if(null == ids || ids.isEmpty()){ return; } int len = ids.size(), i = 0; List<PK> temp = new ArrayList<PK>(); for (; i < len; i++) { temp.add(ids.get(i)); if (i > 0 && i % AssConstant.FLUSH_CRITICAL_VAL == 0) { sqlSessionTemplateASS.delete("removeOfBatch", sqlGenerator.sql_removeOfBatch(temp)); sqlSessionTemplateASS.flushStatements(); temp = new ArrayList<PK>(); } } sqlSessionTemplateASS.delete("removeOfBatch", sqlGenerator.sql_removeOfBatch(temp)); } @Override public void removeAll(){ sqlSessionTemplateASS.delete("removeAll", sqlGenerator.sql_removeAll()); } @Override public void modify(T t) { sqlSessionTemplateASS.update("modify", sqlGenerator.sql_modify(t, currentColumnFieldNames)); } @Override public void modifyOfBatch(List<T> tList) { if(null == tList || tList.isEmpty()){ return; } int len = tList.size(),i=0; for(;i<len;i++){ this.modify(tList.get(i)); if (i > 0 && i % AssConstant.FLUSH_CRITICAL_VAL == 0) { sqlSessionTemplateASS.flushStatements(); } } } @Override public T findOneById(PK id) { Map<String, Object> resultMap = sqlSessionTemplateASS.selectOne( "findOneById", sqlGenerator.sql_findOneById(id)); return handleResult(resultMap, this.entityClass); } @Override public List<T> findAll() { List<Map<String, Object>> resultMapList = sqlSessionTemplateASS .selectList("findAll", sqlGenerator.sql_findAll()); List<T> tList = new ArrayList<T>(resultMapList.size()); for (Map<String, Object> resultMap : resultMapList) { T t = handleResult(resultMap, this.entityClass); tList.add(t); } return tList; } @Override public Long findAllCount() { Long count = sqlSessionTemplateASS .selectOne("findAllCount", sqlGenerator.sql_findAllCount()); return count; } private T handleResult(Map<String, Object> resultMap, Class<T> tClazz) { T t = null; try { t = tClazz.newInstance(); } catch (InstantiationException e) { logger.error("/********************************"); logger.error("封装查询结果时,实例化对象(" + this.entityClass + ")时,出现异常!" + e.getMessage()); logger.error("/********************************"); } catch (IllegalAccessException e) { logger.error("/********************************"); logger.error("封装查询结果时,实例化对象(" + this.entityClass + ")时,出现异常!" + e.getMessage()); logger.error("/********************************"); } for (Map.Entry<String, Object> entry : resultMap.entrySet()) { String key = entry.getKey(); key = currentColumnFieldNames.get(key); Object val = entry.getValue(); ReflectionUtils.invokeSetterMethod(t, key, val); } return t; } }
3)xml配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.szy.ass.core.base.BaseDao"> <!-- 新增 --> <insert id="create"> ${value} </insert> <!-- 批量新增 --> <insert id="createOfBatch"> ${value} </insert> <!-- 根据ID删除 --> <delete id="removeById"> ${value} </delete> <!-- 批量删除 --> <delete id="removeOfBatch"> ${value} </delete> <!-- 批量删除 --> <delete id="removeAll"> ${value} </delete> <!-- 更新 --> <update id="modify">${value}</update> <!-- 根据ID查询单个 --> <select id="findOneById" resultType="hashmap"> ${value} </select> <!-- 查询所有 --> <select id="findAll" resultType="hashmap"> ${value} </select> <!-- 查询总数量 --> <select id="findAllCount" resultType="Long"> ${value} </select> <!-- 获取下一个序列的值 --> <select id="fetchSeqNextval" resultType="Long" flushCache="true"> ${value} </select> </mapper>
4)两个工具类
4.1)生成SQL的工具类
import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.msd.ass.commons.util.DateUtil; import com.msd.ass.commons.util.ReflectionUtils; import com.msd.ass.core.constant.AssConstant; /** * Description: 生成查询数量的SQL */ public class SQLGenerator<T> { protected Logger logger = LoggerFactory.getLogger(this.getClass()); private Set<String> columns; private String tableName; private String columnsStr; private String pkName; private String seq; public SQLGenerator(Set<String> columns, String tableName, String pkName, String seq) { super(); this.columns = columns; this.tableName = tableName; this.pkName = pkName; this.seq = seq; this.columnsStr = StringUtils.join(this.columns, ","); } /** * 生成新增的SQL * * @param t * @param currentColumnFieldNames * @return */ public String sql_create(T t, Map<String, String> currentColumnFieldNames) { List<Object> values = obtainFieldValues(t, currentColumnFieldNames); StringBuilder sql_build = new StringBuilder(); sql_build.append("INSERT INTO ").append(tableName).append("(") .append(columnsStr).append(")values(") .append(StringUtils.join(values, ",")).append(")"); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 生成批量新增的SQL * * @param tList * @param currentColumnFieldNames * @return */ public String sql_createOfBatch(List<T> tList, Map<String, String> currentColumnFieldNames,Object pkVal) { StringBuilder sql_build = new StringBuilder(); int len = tList.size(),i=0; if(StringUtils.isNotEmpty(seq) && null == pkVal){ // ID使用序列 sql_build.append("INSERT INTO ").append(tableName).append("(") .append(columnsStr).append(")"); sql_build.append(" SELECT ").append(seq).append(" , a.* FROM ( "); for (; i < len; i++) { T t = tList.get(i); List<Object> values = obtainFieldValues(t, currentColumnFieldNames); values.remove(seq); if (i == 0) { sql_build.append(" SELECT "); } else { sql_build.append(" UNION ALL SELECT "); } int j = 0, vlen = values.size(); for (; j < vlen; j++) { sql_build.append(values.get(j)).append(" AS T").append(j); if (j != (vlen - 1)) { sql_build.append(","); } } sql_build.append(" FROM DUAL "); } sql_build.append(" ) a "); } else { //ID没有使用序列 sql_build.append("INSERT INTO ").append(tableName).append("(") .append(columnsStr).append(")"); for (; i < len; i++) { T t = tList.get(i); List<Object> values = obtainFieldValues(t, currentColumnFieldNames); if (i == 0) { sql_build.append(" SELECT "); } else { sql_build.append(" UNION ALL SELECT "); } sql_build.append(StringUtils.join(values, ",")).append( " FROM DUAL "); } } String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 提供给生成新增SQL 使用 * * @param t * @param currentColumnFieldNames * @return */ private List<Object> obtainFieldValues(T t, Map<String, String> currentColumnFieldNames) { List<Object> values = new LinkedList<Object>(); for (String column : columns) { Object value = ReflectionUtils.obtainFieldValue(t, currentColumnFieldNames.get(column)); if(StringUtils.equalsIgnoreCase(column, pkName) && null == value){ value = seq; }else{ value = handleValue(value); } values.add(value); } return values; } /** * 处理value * * @param value * @return */ private Object handleValue(Object value) { if (value instanceof String) { value = "\'" + value + "\'"; } else if (value instanceof Date) { Date date = (Date) value; String dateStr = DateUtil.convertDateToString(date, DateUtil.FULL_TIME_FORMAT); value = "TO_TIMESTAMP('" + dateStr + "','YYYY-MM-DD HH24:MI:SS.FF3')"; } else if (value instanceof Boolean) { Boolean v = (Boolean) value; value = v ? 1 : 0; }else if(null == value || StringUtils.isBlank(value.toString())){ value = "''"; } return value; } /** * 生成根据ID删除的SQL * * @param id * @return */ public <PK> String sql_removeById(PK id) { StringBuilder sql_build = new StringBuilder(); sql_build.append("DELETE FROM ").append(this.tableName) .append(" WHERE ").append(pkName).append(" = ").append(id); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 生成根据IDs批量删除的SQL * * @param ids * @return */ public <PK> String sql_removeOfBatch(List<PK> ids) { StringBuilder sql_build = new StringBuilder(); sql_build.append("DELETE FROM ").append(this.tableName) .append(" WHERE ").append(pkName).append(" IN ( 0 "); int len = ids.size(), i = 0; for (; i < len; i++) { PK id = ids.get(i); sql_build.append(",").append(id); if (i > 0 && i % (AssConstant.DELETE_CRITICAL_VAL - 1) == 0) { sql_build.append(")").append(" OR ").append(pkName) .append(" IN ( 0 "); } } sql_build.append(")"); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } public String sql_removeAll() { StringBuilder sql_build = new StringBuilder(); sql_build.append("DELETE FROM ").append(this.tableName); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 生成更新的SQL * * @param t * @param currentColumnFieldNames * @return */ public String sql_modify(T t, Map<String, String> currentColumnFieldNames) { List<String> values = obtainColumnVals(t, currentColumnFieldNames); Object id = ReflectionUtils.obtainFieldValue(t, currentColumnFieldNames.get(pkName)); id = handleValue(id); StringBuilder sql_build = new StringBuilder(); sql_build.append("UPDATE ").append(tableName).append(" SET ") .append(StringUtils.join(values, ",")).append(" WHERE ") .append(pkName).append(" = ").append(id); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 提供给生成更新SQL使用 * * @param t * @param currentColumnFieldNames * @return */ private List<String> obtainColumnVals(T t, Map<String, String> currentColumnFieldNames) { List<String> colVals = new LinkedList<String>(); for (String column : columns) { Object value = ReflectionUtils.obtainFieldValue(t, currentColumnFieldNames.get(column)); if (value != null && !StringUtils.equalsIgnoreCase(column, pkName)) { colVals.add(column + "=" + handleValue(value)); } } return colVals; } /** * 生成根据ID查询的SQL * * @param id * @return */ public <PK> String sql_findOneById(PK id) { StringBuilder sql_build = new StringBuilder(); sql_build.append("SELECT ").append(columnsStr).append(" FROM ") .append(this.tableName) .append(" WHERE ROWNUM = 1 AND " + pkName + " = " + id); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 生成查询所有的SQL * * @return */ public String sql_findAll() { StringBuilder sql_build = new StringBuilder(); sql_build.append("SELECT ").append(columnsStr).append(" FROM ") .append(this.tableName); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } /** * 生成查询数量的SQL * * @return */ public String sql_findAllCount() { StringBuilder sql_build = new StringBuilder(); sql_build.append("SELECT COUNT(1) ").append(" FROM ") .append(this.tableName); String sql = sql_build.toString(); logger.debug("生成的SQL为: " + sql); return sql; } }
4.1)反射的工具类
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Timestamp; import java.text.ParseException; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Description:反射工具类 */ public abstract class ReflectionUtils { private static final Logger logger = LoggerFactory .getLogger(ReflectionUtils.class); /** * 缓存方法 */ private static final Map<Class<?>, Method[]> METHODS_CACHEMAP = new HashMap<Class<?>, Method[]>(); /** * 反射 取值、设值,合并两个对象(Field same only ) * * @param from * @param to */ public static <T> void copyProperties(T fromobj, T toobj, String... fieldspec) { for (String filename : fieldspec) { Object val = ReflectionUtils.invokeGetterMethod(fromobj, filename); ReflectionUtils.invokeSetterMethod(toobj, filename, val); } } /** * 调用Getter方法 * * @param obj * 对象 * @param propertyName * 属性名 * @return */ public static Object invokeGetterMethod(Object obj, String propertyName) { String getterMethodName = "get" + StringUtils.capitalize(propertyName); return invokeMethod(obj, getterMethodName, null, null); } /** * 调用Setter方法,不指定参数的类型 * * @param obj * @param propertyName * @param value */ public static void invokeSetterMethod(Object obj, String propertyName, Object value) { invokeSetterMethod(obj, propertyName, value, null); } /** * 调用Setter方法,指定参数的类型 * * @param obj * @param propertyName 字段名 * @param value * @param propertyType * 为空,则取value的Class */ public static void invokeSetterMethod(Object obj, String propertyName, Object value, Class<?> propertyType) { value = handleValueType(obj,propertyName,value); propertyType = propertyType != null ? propertyType : value.getClass(); String setterMethodName = "set" + StringUtils.capitalize(propertyName); invokeMethod(obj, setterMethodName, new Class<?>[] { propertyType }, new Object[] { value }); } private static Object handleValueType(Object obj, String propertyName, Object value){ String getterMethodName = "get" + StringUtils.capitalize(propertyName); Class<?> argsType = value.getClass();; Class<?> returnType = obtainAccessibleMethod(obj, getterMethodName).getReturnType(); if(argsType == returnType){ return value; } if (returnType == Boolean.class) { String temp = value.toString(); value = (StringUtils.isNotBlank(temp) && Long.valueOf(temp) > 0) ? true : false; } else if (returnType == Long.class) { value = Long.valueOf(value.toString()); }else if(returnType == Date.class){ try { value = SimpleDateFormatFactory.getInstance(DateUtil.FULL_TIME_FORMAT).parse(value.toString()); } catch (ParseException e) { logger.error("类型转型Timpestap-->Date时,发生错误! " + e.getMessage() + "("+value.toString()+")"); } } else if (returnType == Short.class) { value = Short.valueOf(value.toString()); } else if (returnType == BigDecimal.class) { value = BigDecimal.valueOf(Long.valueOf(value.toString())); } else if (returnType == BigInteger.class) { value = BigInteger.valueOf(Long.valueOf(value.toString())); } else if(returnType == String.class){ value = String.valueOf(value); }else if(returnType == Integer.class){ value = Integer.valueOf(value.toString()); } return value; } public static void main(String[] args) throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis()); System.out.println(SimpleDateFormatFactory.getInstance(DateUtil.FULL_TIME_FORMAT).parse(ts.toString())); } /** * 直接调用对象方法,忽视private/protected修饰符 * * @param obj * @param methodName * @param parameterTypes * @param params * @return */ public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes, final Object[] args) { Method method = obtainAccessibleMethod(obj, methodName, parameterTypes); if (method == null) { throw new IllegalArgumentException( "Devkit: Could not find method [" + methodName + "] on target [" + obj + "]."); } try { return method.invoke(obj, args); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } /** * 循环向上转型,获取对象的DeclaredMethod,并强制设置为可访问 如向上转型到Object仍无法找到,返回null * * 用于方法需要被多次调用的情况,先使用本函数先取得Method,然后调用Method.invoke(Object obj,Object... * args) * * @param obj * @param methodName * @param parameterTypes * @return */ public static Method obtainAccessibleMethod(final Object obj, final String methodName, final Class<?>... parameterTypes) { Class<?> superClass = obj.getClass(); Class<Object> objClass = Object.class; for (; superClass != objClass; superClass = superClass.getSuperclass()) { Method method = null; try { method = superClass.getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); return method; } catch (NoSuchMethodException e) { // Method不在当前类定义,向上转型 } catch (SecurityException e) { // Method不在当前类定义,向上转型 } } return null; } /** * 不能确定方法是否包含参数时,通过方法名匹配获得方法 * * @param obj * @param methodName * @return */ public static Method obtainMethod(final Object obj, final String methodName) { Class<?> clazz = obj.getClass(); Method[] methods = METHODS_CACHEMAP.get(clazz); if (methods == null) { // 尚未缓存 methods = clazz.getDeclaredMethods(); METHODS_CACHEMAP.put(clazz, methods); } for (Method method : methods) { if (method.getName().equals(methodName)) return method; } return null; } /** * 直接读取对象属性值 忽视private/protected修饰符,不经过getter函数 * * @param obj * @param fieldName * @return */ public static Object obtainFieldValue(final Object obj, final String fieldName) { Field field = obtainAccessibleField(obj, fieldName); if (field == null) { throw new IllegalArgumentException( "Devkit: could not find field [" + fieldName + "] on target [" + obj + "]"); } Object retval = null; try { retval = field.get(obj); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return retval; } /** * 直接设置对象属性值 忽视private/protected修饰符,不经过setter函数 * * @param obj * @param fieldName * @param value */ public static void setFieldValue(final Object obj, final String fieldName, final Object value) { Field field = obtainAccessibleField(obj, fieldName); if (field == null) { throw new IllegalArgumentException( "Devkit: could not find field [" + fieldName + "] on target [" + obj + "]"); } try { field.set(obj, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } /** * 循环向上转型,获取对象的DeclaredField,并强制设为可访问 如向上转型Object仍无法找到,返回null * * @param obj * @param fieldName * @return */ public static Field obtainAccessibleField(final Object obj, final String fieldName) { Class<?> superClass = obj.getClass(); Class<Object> objClass = Object.class; for (; superClass != objClass; superClass = superClass.getSuperclass()) { try { Field field = superClass.getDeclaredField(fieldName); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { // Field不在当前类定义,向上转型 } catch (SecurityException e) { // Field不在当前类定义,向上转型 } } return null; } }