1.定义注解类:
QueryAuto:
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * ClassName: Query <br/> * Function: 模块关联查询注解<br/> 用于返回list等方法上 */ @Documented @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface QueryAuto { }
QueryField:
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * ClassName: QueryField <br/> * Function: 模块关联查询注解<br/> * <p>比如字典数据,我们表里面都存的字典id,之前的开发模式是在业务模块的sql里各种left join去查询字典名称.</p> * <p>现在的做法是在实体对象的字典id属性上加上此注解,并写上字典名称属性,会自动去查询数据库,赋值于字典名称属性上去.</p> */ @Documented @Inherited @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface QueryField { /** * module:(业务模块编码,默认为Dic 字典模块,其他模块的话需要遵循一定的命名规则, * 详见com.talkweb.query.common.QueryConstant 模块定义常量). <br/> * @author gavin * @return */ public String module() default "Dic"; /** * nameField:(字典数据名称属性字段). <br/> * @author gavin * @return */ public String nameField(); }
2.定义自动查询的属性实体类
import java.io.Serializable; /** * ClassName:QueryFieldEntity <br/> * Function: 需要自动查询的字段属性对象. <br/> */ public class QueryFieldEntity implements Serializable { private static final long serialVersionUID = 1L; private String idFieldName; //id属性的字段名称 private String nameFieldName; //name属性字段名称 private String module; //需要查询的模块名称 public String getIdFieldName() { return idFieldName; } public void setIdFieldName(String idFieldName) { this.idFieldName = idFieldName; } public String getNameFieldName() { return nameFieldName; } public void setNameFieldName(String nameFieldName) { this.nameFieldName = nameFieldName; } public String getModule() { return module; } public void setModule(String module) { this.module = module; } }
3.定义查询工具类:用于获取需要查询的字段
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.annotation.QueryField; import com.query.entity.QueryFieldEntity; /** * ClassName:QueryUtil <br/> * Function: 自动查询工具类. <br/> */ public class QueryUtil { /** * getQueryAutoField:(得到对象中需要自动查询的字段). <br/> * @author gavin * @param object * @return */ public static List<QueryFieldEntity> getQueryAutoField(Object object){ List<QueryFieldEntity> list = new ArrayList<QueryFieldEntity>(); Class<?> cls = object.getClass(); Field[] fields = cls.getDeclaredFields(); List<Field> fieldList = new ArrayList<Field>(Arrays.asList(fields)); //获取父类字段 Class<?> supercls = cls.getSuperclass(); Field[] superfields = supercls.getDeclaredFields(); fieldList.addAll( new ArrayList<Field>(Arrays.asList(superfields))); for (Field field : fieldList) { field.setAccessible(true); QueryField queryField = field.getAnnotation(QueryField.class); if(queryField != null){ QueryFieldEntity entity = new QueryFieldEntity(); entity.setIdFieldName(field.getName()); entity.setNameFieldName(queryField.nameField()); entity.setModule(queryField.module()); list.add(entity); } } return list; } /** * getQueryAutoField:(得到对象中需要自动查询的字段). <br/> * @author gavin * @param object * @return */ public static List<QueryFieldEntity> getSuperQueryAutoField(Object object){ List<QueryFieldEntity> list = new ArrayList<QueryFieldEntity>(); Class<?> supercls = object.getClass().getSuperclass(); Field[] fields = supercls.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); QueryField queryField = field.getAnnotation(QueryField.class); if(queryField != null){ QueryFieldEntity entity = new QueryFieldEntity(); entity.setIdFieldName(field.getName()); entity.setNameFieldName(queryField.nameField()); entity.setModule(queryField.module()); list.add(entity); } } return list; } }
4.定义查询接口:用于处理不同类型的数据
/** * ClassName:Query <br/> * Function: TODO ADD FUNCTION. <br/> * Date: 2017年6月27日 上午9:47:04 <br/> */ public interface Query { /** * doPage:(处理分页数据). <br/> * @author gavin * @param object */ public void doPage(Object object); /** * doList:(处理简单列表数据). <br/> * @author gavin * @param object */ public void doList(Object object); /** * doObject:(处理简单实体对象数据). <br/> * @author gavin * @param object */ public void doObject(Object object); }
package com.query.query.impl; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Component; import com.common.Page; import com.query.adapter.QueryAdapter; import com.query.common.QueryUtil; import com.query.entity.QueryFieldEntity; import com.query.query.Query; /** * ClassName:QueryImpl <br/> * Function: 自动查询实现类. <br/> * Date: 2017年6月27日 上午9:54:02 <br/> * @author gavin * @since JDK 1.6 */ @Component public class QueryImpl implements Query { @Resource(name="queryAdapter") private QueryAdapter queryAdapter; @Override public void doPage(Object object) { Page page = (Page)object; try { Method m = page.getClass().getMethod("getContent"); List list = (List)m.invoke(page); if(list != null && list.size() > 0){ Object o = list.get(0); List<QueryFieldEntity> fieldList = QueryUtil.getQueryAutoField(o); if(fieldList != null && fieldList.size() > 0){ for(Object ob : list){ for(QueryFieldEntity field : fieldList){ queryAdapter.handle(ob, field); } } } } } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } @Override public void doList(Object object) { List list = (List)object; if(list != null && list.size() > 0){ Object o = list.get(0); List<QueryFieldEntity> fieldList = QueryUtil.getQueryAutoField(o); if(fieldList != null && fieldList.size() > 0){ for(Object ob : list){ for(QueryFieldEntity field : fieldList){ queryAdapter.handle(ob, field); } } } } } @Override public void doObject(Object object) { List<QueryFieldEntity> fieldList = QueryUtil.getQueryAutoField(object); if(fieldList != null && fieldList.size() > 0){ for(QueryFieldEntity field : fieldList){ queryAdapter.handle(object, field); } } } }
5.定义查询适配器:用于使用不同的模块(关联表)
package com.talkweb.query.adapter; import java.lang.reflect.Field; import com.config.ApplicationContextRegister; import org.springframework.stereotype.Component; import org.springframework.web.context.ContextLoader; import com.query.entity.QueryFieldEntity; import com.query.query.QueryModule; /** * ClassName:QueryAdapter <br/> * Function: 自动查询适配器. <br/> */ @Component("queryAdapter") public class QueryAdapter { /** * handle:(根据不同模块,适配不同的接口实现类处理查询). <br/> * @author gavin * @param object * @param field */ public void handle(Object object,QueryFieldEntity field) { if(field.getModule() != null && !"".equals(field.getModule())){ //这里必须注意,关于字段上的配置的Module属性,必须要和QueryModule接口实现类的后缀一致, //这里getBean的bean的名称就是queryModuleOf + Module属性!!!! QueryModule queryModule = (QueryModule) ApplicationContextRegister.getApplicationContext() .getBean("queryModuleOf"+field.getModule()); if(queryModule != null){ try { Field idField ; try{ idField = object.getClass().getDeclaredField(field.getIdFieldName()); } catch(NoSuchFieldException e){ idField = object.getClass().getSuperclass().getDeclaredField(field.getIdFieldName()); } idField.setAccessible(true); String id = (String)idField.get(object); if(id != null && !"".equals(id)){ String name = queryModule.query(id,object, field); if(name != null ){ //这里只判断null,不做空判断,因为空可能是数据本身值 Field nameField ; try{ nameField = object.getClass().getDeclaredField(field.getNameFieldName()); } catch(NoSuchFieldException e){ nameField = object.getClass().getSuperclass().getDeclaredField(field.getNameFieldName()); } nameField.setAccessible(true); nameField.set(object, name); } } } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } } } } }
6.定义模块处理类
package com.query.query; import com.query.entity.QueryFieldEntity; /** * ClassName:QueryModule <br/> * Function: 查询具体模块字段接口. <br/> * Date: 2017年6月27日 上午11:30:00 <br/> * @author gavin * @since JDK 1.6 */ public interface QueryModule { /** * query:(查询具体模块方法,可以直接拿到id去做相应查询,然后返回). <br/> * @author gavin * @param id id属性的值 * @param object 具体的实体对象 * @param field 反射需要用到的相关属性 * @return */ public String query(String id, Object object, QueryFieldEntity field); }
package com.query.query.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.entity.pub.Dic; import com.query.entity.QueryFieldEntity; import com.query.query.QueryModule; import com.service.pub.impl.DicService; /** * ClassName:QueryModuleOfDic <br/> * Function: 字典模块查询服务. <br/> */ @Component("queryModuleOfDic") //用于适配器中上下文获取bean public class QueryModuleOfDic implements QueryModule { @Autowired private DicService dicService; @Override public String query(String id, Object object, QueryFieldEntity fieldEntity) { String name = null; if(id != null && !"".equals(id)){ Dic dic = dicService.get(id); //根据id查询字典值 if(dic != null){ name = dic.getName(); } } return name; } }
7.定义查询切面类
import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.annotation.QueryAuto; import com.query.query.Query; /** * ClassName:QueryAop <br/> * Function: 自动查询切面类. <br/> */ @Aspect @Component public class QueryAop { @Autowired private Query query; private static final Logger LOG = Logger.getLogger(QueryAop.class); //execution为执行的意思,*代表任意返回值,然后是包名,.*意思是包下面的所有子包 *(..)代表各种方法. && @annotation(queryAuto) 表示并且方法上有为queryAuto的注解 @Pointcut(value="execution(* com.service..*.*(..)) && @annotation(queryAuto) " , argNames="queryAuto") private void queryAuto(QueryAuto queryAuto){}//定义流程切入点 /** * queryAuto:(自动查询切面方法). <br/> * @author gavin * @param point * @param queryAuto * @return * @throws Throwable */ @Around(value = "queryAuto(queryAuto)" , argNames="queryAuto") public Object queryAuto(ProceedingJoinPoint point,QueryAuto queryAuto) throws Throwable { long start = System.currentTimeMillis(); System.out.println("QueryAuto--->进入自动查询AOP"); LOG.info("QueryAuto--->进入自动查询AOP"); Object object = point.proceed();//执行方法 if(object != null){ if(object instanceof com.talkweb.common.Page){ //返回类型为page对象 query.doPage(object); } else if(object instanceof java.util.List){ //返回类型为List query.doList(object); } else if(object instanceof java.util.Map){ //返回类型为Map //map 不作处理 } else if(object.getClass().getName().indexOf("com.talkweb.entity") >=0 ){ //默认为系统业务实体对象,如果为其他的比如:String Integer...基础数据类型,不作处理 query.doObject(object); } } System.out.println("QueryAuto--->退出自动查询AOP方法。方法执行时长: "+ (System.currentTimeMillis() - start) + "ms"); LOG.info("QueryAuto--->退出自动查询AOP方法。方法执行时长: "+ (System.currentTimeMillis() - start) + "ms"); return object; } }
8.使用
1.在实体类中定义查询字段
@QueryField(module=QueryConstant.MODULE_AssumeComPany,nameField="fill_park_name") private String fill_park_pid; //填报所在园区,当前填报人所在的园区 private String fill_park_name;
2.在service类中添加自动查询注解
@QueryAuto @Override public Page<NatureMainEntity> list(int pageNum, int pageSize, Map<String, Object> parameter) { PageHelper.startPage(pageNum, pageSize, pageNum == 0 ? false : true); List<NatureMainEntity> reuslt = getDao().list(parameter); Page<NatureMainEntity> page = new Page<NatureMainEntity>(reuslt); return page; }