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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值