`

Java 注释,反射,泛型的综合应用

阅读更多
    前面项目中有个change history的功能,多个模块的多个对象都需要记录change history,也就是需要记录对象属性值的变化历史,以便追踪查询。
    为此,我设计了ChangeHistory和ChangeDetail两个类,用于记录历史。
    但由于此需求是多个模块共同需要的,我们希望将此功能抽出来,设计出一个公共的util功能供系统各模块调用。
    由于各个模块的对象都不一样,为了统一接口,我们就应该用到泛型。由于各个对象的哪些属性需要比较,属性的类型也不同,对象对应的表名不同,为了标记这些对象的不同,就使用了注释。有了注释,在获取和记录change信息的时候,就需要读取这些注释,所以也需要用到反射。
    一个简单的功能,就集中用到了java的注释,反射,泛型,通过这个例子,也能很好的初步掌握java的这三项基本知识。而对于我们常用到的一些java框架,比如SSH,这三项基本知识也是实现他们的基石。


    下面的类中,util类是ChangeHistoryUtil,ChangeHistory和ChangeDetail是用语保存变化历史的类,ColumnName、ComparableField、IdField、JavaTypeAdapter、Table、ValueType是注释。最后面的MoqEntity 和之后的一小段代码是实际使用的例子。   


下面是详细的各个类的实现:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.covisint.supplyonline.utils.dbUtil.annotation.ColumnName;
import com.covisint.supplyonline.utils.dbUtil.annotation.Relation;

@TableName(name="SO_CHANGE_HISTORY")
public class ChangeHistory implements Serializable {

/**
*
*/
private static final long serialVersionUID = 6848528239996096783L;

@ColumnName(name="CH_ID",primaryKey=true)
private long chId;

@ColumnName(name="FUNCTION_CODE")
private String functionCode;

@ColumnName(name="CHANGE_ACTION")
private String changeAction;

@ColumnName(name="TABLE_NAME")
private String tableName;

@ColumnName(name="ID_COLUMN_NAME")
private String idColumnName;

@ColumnName(name="OBJECT_ID")
private long objectId;

@ColumnName(name="UPDATED_DATE")
private Date updateDate;

private String updateDateStr;

@ColumnName(name="UPDATED_BY")
private String updateBy;

@Relation(fKColumn="CH_ID",relationType="many-to-one",mapingClassName="com.covisint.supplyonline.entity.ChangeDetail")
private List<ChangeDetail> details;

public long getChId() {
return chId;
}
public void setChId(long chId) {
this.chId = chId;
}
public String getFunctionCode() {
return functionCode;
}
public void setFunctionCode(String functionCode) {
this.functionCode = functionCode;
}
public String getChangeAction() {
return changeAction;
}
public void setChangeAction(String changeAction) {
this.changeAction = changeAction;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public List<ChangeDetail> getDetails() {
if(details == null){
details = new ArrayList<ChangeDetail>();
}
return details;
}
public void setDetails(List<ChangeDetail> details) {
this.details = details;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getIdColumnName() {
return idColumnName;
}
public void setIdColumnName(String idColumnName) {
this.idColumnName = idColumnName;
}
public long getObjectId() {
return objectId;
}
public void setObjectId(long objectId) {
this.objectId = objectId;
}
public String getUpdateDateStr() {
return updateDateStr;
}
public void setUpdateDateStr(String updateDateStr) {
this.updateDateStr = updateDateStr;
}

}


import java.io.Serializable;

import com.covisint.supplyonline.utils.dbUtil.annotation.ColumnName;
import com.covisint.supplyonline.utils.dbUtil.annotation.TableName;

@TableName(name="SO_CHANGE_HISTORY_DETAIL")

public class ChangeDetail implements Serializable {

/**
*
*/
private static final long serialVersionUID = -977083550981628736L;

@ColumnName(name="CH_DETAIL_ID",primaryKey=true)
private long detailId;

@ColumnName(name="CH_ID")
private long chId;

@ColumnName(name="CHANGED_ITEM")
private String changeItem;

@ColumnName(name="FROM_VALUE")
private String fromValue;

@ColumnName(name="TO_VALUE")
private String toValue;

@ColumnName(name="VALUE_TYPE")
private long valueType;

private String comment;

public long getDetailId() {
return detailId;
}
public void setDetailId(long detailId) {
this.detailId = detailId;
}
public long getChId() {
return chId;
}
public void setChId(long chId) {
this.chId = chId;
}
public String getFromValue() {
return fromValue;
}
public void setFromValue(String fromValue) {
this.fromValue = fromValue;
}
public String getToValue() {
return toValue;
}
public void setToValue(String toValue) {
this.toValue = toValue;
}
public String getChangeItem() {
return changeItem;
}
public void setChangeItem(String changeItem) {
this.changeItem = changeItem;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public long getValueType() {
return valueType;
}
public void setValueType(long valueType) {
this.valueType = valueType;
}


}





package com.covisint.supplyonline.utils.comparator;


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.covisint.supplyonline.entity.ChangeDetail;
import com.covisint.supplyonline.entity.ChangeHistory;
import com.covisint.supplyonline.entity.UserEntity;
import com.covisint.supplyonline.utils.comparator.ColumnName;
import com.covisint.supplyonline.utils.comparator.ComparableField;
import com.covisint.supplyonline.utils.comparator.IdField;
import com.covisint.supplyonline.utils.comparator.SAICHKComparatorConstants;
import com.covisint.supplyonline.utils.comparator.Table;
import com.covisint.supplyonline.utils.comparator.ValueType;
import com.covisint.supplyonline.utils.comparator.adapters.TypeAdapter;


public class ChangeHistoryUtil {
      @SuppressWarnings({ "unchecked", "rawtypes" })
public  static <T> ChangeHistory buildChangeHistory(T old,T now,UserEntity user,String functionCodeKey,String changeActionKey) throws IllegalArgumentException, IllegalAccessException {
     
      ChangeHistory changeHistory = new ChangeHistory();
      String tableName = old.getClass().getAnnotation(Table.class).tableName();
      String idColumnName = old.getClass().getAnnotation(Table.class).idColumn();
      Date updateDate = new Date();
      List<ChangeDetail> details = new ArrayList<ChangeDetail>();
    Field[] fields = old.getClass().getDeclaredFields();
    long objectId=0;
  if (fields != null) {
for (Field field : fields) {
if (field.isAnnotationPresent(ComparableField.class)) {
field.setAccessible(true);
if ( ( field.get(old)==null && field.get(now)==null ) || ( field.get(old)==null && field.get(now).equals("") ) || ( field.get(now)==null && field.get(old).equals("") )  || (field.get(old)!=null && (field.get(old)).equals(field.get(now)) )  ) {
// System.out.println("equals");
} else {
// System.out.println(field.get(now) + " is different than " + field.get(old));
ChangeDetail changeDetail = new ChangeDetail();

changeDetail.setChangeItem(field.getAnnotation(ColumnName.class).column());

if (field.isAnnotationPresent(ValueType.class)) {
changeDetail.setValueType(field.getAnnotation(ValueType.class).type());
}else {
changeDetail.setValueType(SAICHKComparatorConstants.normal_value);
}

if(field.isAnnotationPresent(JavaTypeAdapter.class)){

final Object _old = field.get(old);
final Object _new = field.get(now);
Class<? extends TypeAdapter> clas = field.getAnnotation(JavaTypeAdapter.class).value();
TypeAdapterProcess aa = new TypeAdapterProcess();
String  _oldV = aa.process(_old, clas);
String  _newV = aa.process(_new, clas);
if(!_oldV.equals(_newV)){
changeDetail.setFromValue(_oldV);
changeDetail.setToValue(_newV);
details.add(changeDetail);
}

}else{


java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
if(field.get(old)!=null && field.get(old).getClass().getName().indexOf(".Date")>0){
changeDetail.setFromValue(simpleDateFormat.format(field.get(old)));
}
else
{

changeDetail.setFromValue(field.get(old)==null?"":field.get(old).toString());
}

if(field.get(now)!=null && field.get(now).getClass().getName().indexOf(".Date")>0){
changeDetail.setToValue(simpleDateFormat.format(field.get(now)));
}
else
{
changeDetail.setToValue(field.get(now)==null?"":field.get(now).toString());
}
details.add(changeDetail);
}



}
field.setAccessible(false);
}
if (field.isAnnotationPresent(IdField.class)) {
field.setAccessible(true);
objectId = field.getLong(now);
field.setAccessible(false);
}
}
  }
  changeHistory.setFunctionCode(functionCodeKey);
  changeHistory.setChangeAction(changeActionKey);
  changeHistory.setIdColumnName(idColumnName);
  changeHistory.setTableName(tableName);
  changeHistory.setUpdateBy(user.getUserCode());
  changeHistory.setUpdateDate(updateDate);
  changeHistory.setDetails(details);
  changeHistory.setObjectId(objectId);
  return changeHistory;
      }
}









package com.covisint.supplyonline.utils.comparator;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnName {
public String column();
}



package com.covisint.supplyonline.utils.comparator;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ComparableField {

}


package com.covisint.supplyonline.utils.comparator;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;


@Retention(RetentionPolicy.RUNTIME)
public @interface IdField {

}


package com.covisint.supplyonline.utils.comparator;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import com.covisint.supplyonline.utils.comparator.adapters.TypeAdapter;

@Retention(RUNTIME) @Target({FIELD}) 
public @interface JavaTypeAdapter {

Class <? extends TypeAdapter> value();
}



package com.covisint.supplyonline.utils.comparator;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String tableName();

String idColumn();
}



package com.covisint.supplyonline.utils.comparator;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;


@Retention(RetentionPolicy.RUNTIME)
public @interface ValueType {
public long type();
}




package com.covisint.supplyonline.saichk.entity;

import java.io.Serializable;
import java.util.Date;

import com.covisint.supplyonline.saichk.utils.SAICKUtil;
import com.covisint.supplyonline.utils.comparator.ColumnName;
import com.covisint.supplyonline.utils.comparator.ComparableField;
import com.covisint.supplyonline.utils.comparator.IdField;
import com.covisint.supplyonline.utils.comparator.ValueType;
import com.covisint.supplyonline.utils.comparator.SAICHKComparatorConstants;
import com.covisint.supplyonline.utils.comparator.Table;



@Table(tableName = "SO_MOQ", idColumn = "MOQ_ID")
public class MoqEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 823354654756518422L;

@IdField
private long moqId;

private long partMastId;

private long supplierId;

private String supplier;

private String partNo;

private String partName;

@ComparableField
@ColumnName(column = SAICHKComparatorConstants.CI_MASTER_DATA_MOQ_QUANTITY)
private long moqQuantity;

@ComparableField
@ColumnName(column = SAICHKComparatorConstants.CI_MASTER_DATA_VALID_FROM)
@ValueType(type = SAICHKComparatorConstants.valid_date)
private Date validFrom;

@ComparableField
@ColumnName(column = SAICHKComparatorConstants.CI_MASTER_DATA_VALID_TO)
@ValueType(type = SAICHKComparatorConstants.valid_date)
private Date validTo;

@ComparableField
@ColumnName(column = SAICHKComparatorConstants.CI_MASTER_DATA_STATUS)
@ValueType(type = SAICHKComparatorConstants.shorten_value)
private String status;

private String unit;


public long getMoqId() {
return moqId;
}

public void setMoqId(long moqId) {
this.moqId = moqId;
}

public long getMoqQuantity() {
return moqQuantity;
}

public void setMoqQuantity(long moqQuantity) {
this.moqQuantity = moqQuantity;
}

public String getUnit() {
return unit;
}

public void setUnit(String unit) {
this.unit = unit;
}

private String updateBy;

private Date updateDate;


public long getPartMastId() {
return partMastId;
}

public void setPartMastId(long partMastId) {
this.partMastId = partMastId;
}

public long getSupplierId() {
return supplierId;
}

public void setSupplierId(long supplierId) {
this.supplierId = supplierId;
}

public Date getValidFrom() {
return validFrom;
}

public void setValidFrom(Date validFrom) {
this.validFrom = validFrom;
}

public Date getValidTo() {
return validTo;
}

public void setValidTo(Date validTo) {
this.validTo = validTo;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public String getUpdateBy() {
return updateBy;
}

public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}

public Date getUpdateDate() {
return updateDate;
}

public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}

public String getSupplier() {
return supplier;
}

public void setSupplier(String supplier) {
this.supplier = supplier;
}

public String getPartNo() {
return partNo;
}

public void setPartNo(String partNo) {
this.partNo = partNo;
}

public String getPartName() {
return partName;
}

public void setPartName(String partName) {
this.partName = partName;
}

public String getValidFromWeekFormat() {
return SAICKUtil.getValidWeekStr(validFrom);
}

public String getValidToWeekFormat() {
return SAICKUtil.getValidWeekStr(validTo);
}

}

示例util类的使用方法:
MoqEntity moqEntity = buildMoqEntity(
pcCommand, userEntity);

MoqEntity oldMoqEntity = new MoqEntity();
if (pcCommand.getMoqId()>0)
oldMoqEntity = masterDataService.getMoqById(pcCommand.getMoqId());

long moqId =  masterDataService.operatMoq(moqEntity);

if(pcCommand.getMoqId()>0) {
ChangeHistory chy = ChangeHistoryUtil.buildChangeHistory(oldMoqEntity, moqEntity, userEntity,
SAICHKComparatorConstants.FC_MOQ, SAICHKComparatorConstants.CA_EDIT);
changeService.writeToChangeHistory(chy);
}



分享到:
评论

相关推荐

    java,反射+注释+泛型+jdbc mysql练习项目代码

    在本项目中,"反射+注释+泛型+jdbc mysql练习项目代码" 提到了几个关键的Java编程概念,我们将一一进行深入探讨。 1. **Java反射**:反射API允许我们在运行时动态地获取类的信息(如类名、方法名、参数类型等)并...

    java 反射实例,大量注释,简单易懂

    以下是对"java 反射实例,大量注释,简单易懂"这个主题的详细解释: 1. **反射基础**: - Java反射API主要由`java.lang.reflect`包提供,包括`Class`,`Constructor`,`Method`和`Field`等类。 - `Class`类代表...

    Java反射技术的一般应用

    在向学生讲解Class.forName()方法的使用时,有时需要扩展讲解为什么这样书写的原理,于是,扩展讲解Java反射技术可以查看被监视类的方法(构造方法和普通方法)、公有属性的功能,以达到封闭功能的效果。该例子使用...

    java 通过反射获取类上注解,方法上注解,注解里的值及方法参数

    反射(Reflection)是Java的一个强大特性,允许程序在运行时检查类、接口、字段和方法等信息。本教程将深入探讨如何通过反射获取类、方法上的注解以及注解中的值和方法参数。 1. **注解的定义与使用** 注解以`@`...

    Java 基础(Java-8).zip

    (JSP)ServletJava 多项选择题Java 设计模式休眠Spring 框架基础目录介绍Java 架构Java 数据类型Java 方法Java 函数式编程Java Lambda 表达式Java 类Java 构造函数Java 数组Java 字符串Java 反射Java 流Java 正则...

    链表+泛型+反射实现自定义的LinkedList集合类

    通过对这个自定义LinkedList的深入学习,你可以更深入地理解Java的链表数据结构、泛型的使用以及反射的强大能力。这对于提升Java编程技巧,特别是对于理解和处理复杂数据结构以及提高代码灵活性是非常有价值的。同时...

    JavaAPI部分练习代码全注释

    7. **反射机制**:`java.lang.reflect`包提供了反射API,可以在运行时动态获取类的信息并操作对象,如创建对象、调用方法、访问字段。 8. **多线程**:除了`Thread`类,`java.util.concurrent`包提供了高级的并发...

    疯狂Java讲义+源代码

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制。...

    疯狂Java讲义 第3版 PDF电子书下载 带书签目录 完整版.rar

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、JavaGUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制。...

    疯狂java讲义源代码

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制。...

    java进阶技术:泛型、反射、注解

    泛型是Java SE 1.5的新特性,好处是在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。JAVA反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对以后学习框架有很大的帮助。...

    《疯狂Java讲义》随书光盘

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通讯编程和Java反射机制;...

    疯狂Java讲义代码

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制。...

    java反射机制详解

    同时,由于Java的泛型信息在编译后会被擦除,反射处理泛型时需额外注意。 5. **注解处理**:通过反射,我们可以获取类、方法、字段上的注解,并进行相应的逻辑处理。 6. **动态代理**:Java的反射机制还支持动态...

    java疯狂讲义

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、JavaGUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制。...

    Java反射技术的一般应用(放低分数供大家学习)

    在向学生讲解Class.forName()方法的使用时,有时需要扩展讲解为什么这样书写的原理,于是,扩展讲解Java反射技术可以查看被监视类的方法(构造方法和普通方法)、公有属性的功能,以达到封闭功能的效果。该例子使用...

    Java开发技术大全(500个源代码).

    HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用Java开发的Applet小程序。 firstApplet.htm 用来装载Applet的网页文件 第2章 示例描述:本章介绍开发Java的基础语法知识。 ...

    疯狂Java讲义 第3版 完整版(Part3)

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通讯编程和Java反射机制;...

    疯狂java讲义+源码

    全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编程、JDBC数据库编程、Java注释、Java的IO流体系、Java多线程编程、Java网络通信编程和Java反射机制。...

Global site tag (gtag.js) - Google Analytics