package steed.util.base; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.Id; import javax.persistence.IdClass; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import steed.hibernatemaster.annotation.FuzzyQuery; import steed.hibernatemaster.annotation.FuzzyQuery.FuzzyQuerystrategy; import steed.hibernatemaster.domain.BaseDomain; import steed.hibernatemaster.domain.BaseRelationalDatabaseDomain; import steed.hibernatemaster.domain.UnionKeyDomain; import steed.hibernatemaster.exception.DomainIdAnnotationNotFoundException; import steed.hibernatemaster.util.DaoUtil; import steed.util.reflect.ReflectUtil; /** * 实体类工具类 * @author 战马 * */ public class DomainUtil{ private static Logger logger = LoggerFactory.getLogger(DomainUtil.class); /** * 获取实体类的hashcode * @param baseDomain * @return */ public static int domainHashCode(BaseDomain baseDomain){ if (baseDomain == null) { return 0; } try { Object tempObject = getDomainId(baseDomain); if (tempObject == null) { return -1; }else { return tempObject.hashCode(); } } catch (Exception e) { e.printStackTrace(); return 1; } } /** * 净化,把domain关联的实体类设置成空,一般用于给前端返回json数据 * */ public static void purify(BaseDomain domain){ List<Field> allFields = ReflectUtil.getAllFields(domain); for(Field temp:allFields){ if (BaseDomain.class.isAssignableFrom(temp.getType())) { temp.setAccessible(true); try { temp.set(domain, null); } catch (IllegalArgumentException | IllegalAccessException e) { steed.util.logging.LoggerFactory.getLogger().warn("净化实体类出错",e); } } } } /** * 获取实体类ID的名字 * @param clazz * @return */ public static String getDomainIDName(Class<? extends BaseDomain> clazz){ /** * 如果是联合主键实体类则返回domainID,因为联合主键类必须实现getDomainID()方法 */ if (clazz.getAnnotation(IdClass.class) != null) { return "domainID"; } try { Method m = getIDmethod(clazz); if (m != null) { String name = m.getName(); if (name.startsWith("is")) { return name.substring(2, 3).toLowerCase() + name.substring(3) ; }else { return name.substring(3, 4).toLowerCase() + name.substring(4) ; } } } catch (Exception e) { throw createFindIdException(clazz, e); } try { Field f = getIDfield(clazz); if (f != null) { return f.getName(); } } catch (Exception e) { e.printStackTrace(); throw createFindIdException(clazz, e); } throw createIDNotfoundException(clazz); } /** * 获取实体类ID Class * @param clazz * @return */ @SuppressWarnings("unchecked") public static Class<? extends Serializable> getDomainIDClass(Class<? extends BaseDomain> clazz){ /** * 如果是联合主键实体类则返回domainID,因为联合主键类必须实现getDomainID()方法 */ IdClass annotation = clazz.getAnnotation(IdClass.class); if (annotation != null) { return annotation.value(); } try { Field f = ReflectUtil.getDeclaredField(clazz, getDomainIDName(clazz)); if (f != null) { return (Class<? extends Serializable>) f.getType(); } } catch (Exception e) { e.printStackTrace(); throw createFindIdException(clazz, e); } throw createIDNotfoundException(clazz); } public static BaseDomain fillID2Domain(Serializable id,BaseDomain baseDomain){ Class<? extends BaseDomain> domainClass = baseDomain.getClass(); Field iDfield = getIDfield(domainClass); try { if (iDfield != null) { iDfield.setAccessible(true); iDfield.set(baseDomain, id); return baseDomain; }else { Method iDmethod = getIDmethod(domainClass); if (iDmethod != null) { domainClass.getMethod(iDmethod.getName().replaceFirst("get", "set"),iDmethod.getReturnType()).invoke(baseDomain, id); return baseDomain; } } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(domainClass.getName()+"中没有id字段或ID的set方法!!"); } throw new RuntimeException(domainClass.getName()+"中没有id字段或ID的set方法!!"); } /** * 获取实体类主键 * @param baseDomain * @return */ public static Serializable getDomainId(BaseDomain baseDomain){ if (baseDomain instanceof UnionKeyDomain) { return ((UnionKeyDomain)baseDomain).getDomainID(); } Class<? extends BaseDomain> clazz = baseDomain.getClass(); try { Method m = getIDmethod(clazz); if (m != null) { return (Serializable) m.invoke(baseDomain); } } catch (Exception e) { e.printStackTrace(); throw createFindIdException(clazz, e); } try { Field f = getIDfield(clazz); if (f != null) { return (Serializable) f.get(baseDomain); } } catch (Exception e) { e.printStackTrace(); throw createFindIdException(clazz, e); } throw createIDNotfoundException(clazz); } private static RuntimeException createFindIdException(Class<? extends BaseDomain> clazz, Exception e) { logger.error("在"+ clazz.getName()+"找到含有"+Id.class.getName()+"注解的get方法,或字段时出现异常。", e); return new RuntimeException("在"+ clazz.getName()+"找到含有"+Id.class.getName()+"注解的get方法,或字段时出现异常。", e); } private static DomainIdAnnotationNotFoundException createIDNotfoundException(Class<? extends Object> clazz) { logger.error("在"+clazz.getName()+"中找不到含有"+Id.class.getName()+"注解的get方法,或字段。"); DomainIdAnnotationNotFoundException exception = new DomainIdAnnotationNotFoundException("在"+ clazz.getName()+"中找不到含有"+Id.class.getName()+"注解的get方法,或字段。"); exception.printStackTrace(); return exception; } /** * 判断实体类和另一个对象是否相等 * @param baseDomain * @param obj2 * @return */ public static boolean domainEquals(BaseDomain baseDomain,Object obj2){ if (baseDomain == null) { return obj2 == null; }else if (obj2 == null) { return false; } // Class<? extends BaseDomain> clazz = baseDomain.getClass(); Class<? extends Object> clazz2 = obj2.getClass(); if (BaseDomain.class.isAssignableFrom(clazz2)) { /*Method iDmethod = getIDmethod(clazz); if (iDmethod != null) { Object tempObject; try { tempObject = iDmethod.invoke(baseDomain); return BaseUtil.objectEquals(iDmethod.invoke(obj2),tempObject); } catch (Exception e) { e.printStackTrace(); throw createFindIdException(clazz, e); } } Field f = getIDfield(clazz); if (f != null) { try { Object tempObject = f.get(baseDomain); return BaseUtil.objectEquals(f.get(obj2),tempObject); } catch (Exception e) { e.printStackTrace(); throw createFindIdException(clazz, e); } } createIDNotfoundException(clazz2);*/ Serializable domainId = getDomainId(baseDomain); Serializable id2 = getDomainId((BaseDomain) obj2); if (domainId == null) { return id2 == null; }else if(id2 == null){ return false; }else { return id2.equals(domainId); } }else if(ReflectUtil.isObjBaseData(obj2)){ Serializable domainId = getDomainId(baseDomain); return obj2.equals(domainId); }else { return false; } } /** * 获取ID字段 * @param clazz * @return */ @SuppressWarnings("unchecked") public static Field getIDfield(Class<? extends BaseDomain> clazz) { if (clazz.getAnnotation(IdClass.class) != null) { StringBuffer sb = new StringBuffer("按照约定含有"); sb.append(IdClass.class.getName()); sb.append("注解的domain不能有ID字段!!!只能有getDomainID()方法。"); throw new RuntimeException(sb.toString()); } Field[] fields = clazz.getDeclaredFields(); for (Field f:fields) { f.setAccessible(true); Annotation temp = f.getAnnotation(Id.class); if (temp == null) { continue; } return f; } if (clazz == BaseDomain.class) { return null; } return getIDfield((Class<? extends BaseDomain>)clazz.getSuperclass()); } @SuppressWarnings("unchecked") public static Method getIDmethod(Class<? extends BaseDomain> clazz) { if (clazz.getAnnotation(IdClass.class) != null) { try { return clazz.getDeclaredMethod("getDomainID"); } catch (NoSuchMethodException e) { throw new RuntimeException("含有"+IdClass.class.getName()+ "的domain必须实现"+UnionKeyDomain.class.getName()+"接口!!!",e); } } Method[] methods = clazz.getDeclaredMethods(); for (Method m:methods) { Annotation aa = m.getAnnotation(Id.class); if (aa == null) { continue; } return m; } if (clazz == BaseDomain.class) { return null; } return getIDmethod((Class<? extends BaseDomain>)clazz.getSuperclass()); } /** * 把fill中不为null的字段填充给filled * @param filled * @param fill * @param fieldsNotSkip 即使为null也不跳过的字段,如果没有可以传个null */ public static <T> void fillDomain(T filled,T fill,Collection<String> fieldsNotSkip){ fillDomain(filled, fill, fieldsNotSkip, false); } /* public static <T> List<DifferenceField> getDifferenceField(T oldObject,T newObj,Collection<String> fieldsNotSkip){ return getDifferenceField(oldObject, newObj, fieldsNotSkip, false); } */ /** * 获取newObj中不为空的字段跟oldObj中值不一样的字段,一般用于更新功能比较用户修改了哪些东西 * @param oldObject * @param newObj * @param fieldsNotSkip 即使为null也不跳过的字段,如果没有可以传个null * @param strictlyMode 严格模式,如果为true则 字段==null才算空,否则调用BaseUtil.isObjEmpty判断字段是否为空 * @see BaseUtil#isObjEmpty * @return */ public static <T> List<DifferenceField> getDifferenceField(T oldObject,T newObj,Collection<String> fieldsNotSkip,boolean strictlyMode){ List<Field> fields = ReflectUtil.getAllFields(newObj); List<DifferenceField> differenceFields = new ArrayList<>(); try { if(fieldsNotSkip == null){ fieldsNotSkip = new ArrayList<String>(); } for (Field f:fields) { if(ReflectUtil.isFieldFinal(f)){ continue; } f.setAccessible(true); Object newField = getFieldValue(newObj, f); boolean isNull; if (strictlyMode) { isNull = newField == null; }else { isNull = BaseUtil.isObjEmpty(newField); } if (!isNull || fieldsNotSkip.contains(f.getName())) { Object oldField = getFieldValue(oldObject, f); if ((newField == null && oldField != null )|| ( newField != null && !newField.equals(oldField))) { differenceFields.add(new DifferenceField(f.getName(), newObj.getClass(), newField, oldField,f)); } } } } catch (IllegalArgumentException | IllegalAccessException e) { steed.util.logging.LoggerFactory.getLogger().info("获取字段值出错",e); } return differenceFields; } private static <T> Object getFieldValue(T target, Field f) throws IllegalAccessException { Object field = ReflectUtil.getFieldValueByGetter(target, f.getName()); if (field == null) { field = f.get(target); } return field; } /** * 把fill中不为null的字段填充给filled * @param filled * @param fill * @param fieldsNotSkip 即使为null也不跳过的字段,如果没有可以传个null * @param strictlyMode 严格模式,如果为true则 字段==null才算空, * 否则调用BaseUtil.isObjEmpty判断字段是否为空 * @see BaseUtil#isObjEmpty * @return * @return fill中不为空的字段跟filled中值不一样的字段 */ public static <T> List<DifferenceField> fillDomain(T filled,T fill,Collection<String> fieldsNotSkip,boolean strictlyMode){ List<DifferenceField> differenceField = getDifferenceField(filled, fill, fieldsNotSkip, strictlyMode); for (DifferenceField temp:differenceField) { try { temp.getField().set(filled, temp.getNewField()); } catch (IllegalArgumentException | IllegalAccessException e) { steed.util.logging.LoggerFactory.getLogger().info("设置字段出错",e); } } return differenceField; } private static void fuzzyQueryInitialize(String prefix,BaseDomain obj,boolean skipId,String ...fieldsSkip){ List<String> fieldsSkipList = new ArrayList<String>(); Collections.addAll(fieldsSkipList, fieldsSkip); List<Field> allFields = ReflectUtil.getAllFields(obj); for (Field f:allFields) { try { if (DaoUtil.isSelectIndex(f.getName()) > 0) { continue; } f.setAccessible(true); Object value = f.get(obj); if (!fieldsSkipList.contains(prefix+f.getName())) { if (value instanceof String && !StringUtil.isStringEmpty((String) value)) { if (skipId && ReflectUtil.getAnnotation(Id.class, obj.getClass(), f) != null) { continue; } FuzzyQuery annotation = ReflectUtil.getAnnotation(FuzzyQuery.class, obj.getClass(), f); if (annotation == null) { f.set(obj, "%"+value+"%"); }else { FuzzyQuerystrategy value2 = annotation.value(); switch (value2) { case left: f.set(obj, "%"+value); break; case right: f.set(obj, value+"%"); break; case both: f.set(obj, "%"+value+"%"); break; default: break; } } }else if (value instanceof BaseDomain && BaseUtil.isObjEmpty(DomainUtil.getDomainId((BaseDomain) value))) { fuzzyQueryInitialize(f.getName()+".", (BaseDomain) value,skipId, fieldsSkip); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } /** * 初始化查询实体类模糊查询 * @param obj * @param fieldsSkip 跳过的字段,不跳请传空 * * @see FuzzyQuery */ public static void fuzzyQueryInitialize(BaseDomain obj,String ...fieldsSkip){ fuzzyQueryInitialize(obj, true, fieldsSkip); } /** * 初始化查询实体类模糊查询 * @param obj * @param fieldsSkip 跳过的字段,不跳请传空 * * @see FuzzyQuery */ public static void fuzzyQueryInitialize(BaseDomain obj,boolean skipId,String ...fieldsSkip){ fuzzyQueryInitialize("", obj,skipId, fieldsSkip); } /** * 把obj中非空字段放到map * @param obj * @return map */ public static Map<String, Object> putField2Map(Object obj) { Map<String, Object> map = new HashMap<>(); putField2Map(obj, map, ""); return map; } /** * 把obj中非空字段放到map */ public static void putField2Map(Object obj,Map<String, Object> map,String prefixName) { putField2Map(obj, map, prefixName, true); } public static void putField2Map(Object obj,Map<String, Object> map,String prefixName,boolean getFieldByGetter) { try { List<Field> Fields = ReflectUtil.getNotFinalFields(obj); for (Field f:Fields) { String fieldName = f.getName(); Object value = null; if (getFieldByGetter) { value = ReflectUtil.getFieldValueByGetter(obj, fieldName); } if(value == null){ f.setAccessible(true); value = f.get(obj); } if (value == null) { continue; } if (!(value instanceof BaseRelationalDatabaseDomain) ) { map.put(prefixName + fieldName, value); }else { putField2Map(value, map,prefixName + fieldName +"."); } } } catch (IllegalArgumentException | IllegalAccessException e) { steed.util.logging.LoggerFactory.getLogger().debug("putField2Map出错",e); } } public static void setDomainId(BaseDomain baseDomain, Serializable serializable) { Class<? extends BaseDomain> class1 = baseDomain.getClass(); String domainIDName = getDomainIDName(class1); String fieldSetterName = StringUtil.getFieldSetterName(domainIDName); try { Method method = class1.getMethod(fieldSetterName, serializable.getClass()); method.invoke(baseDomain, serializable); } catch (NoSuchMethodException e) { throw new RuntimeException(class1+"中没有"+fieldSetterName+"方法", e); } catch (SecurityException | IllegalAccessException | InvocationTargetException | IllegalArgumentException e) { throw new RuntimeException(class1+"中的"+fieldSetterName+"方法有误", e); } } }