这个问题的背景就是我要call一个第三方的接口,但是这个接口返回的字段的命名格式并非java标准的命名格式,所以当我用java中的entity去接受的时候,就会因为字段定义不一致的问题而产生大量map的工作量。这个工作量很蠢,而且纯粹是机械的一个个去set。有一两个entity还好,但是有十几个entity的时候难道还要手动一个个的去set吗?
这时我领导提供了一个超级牛逼的思路:反射
讲道理反射这个词我只在两个地方使用过,一个是考试的时候,一个是面试的时候,通过获取类的二进制字节码文件获取这个类的全部信息巴拉巴拉一大堆。但真正在生产中,我倒是真的没用过了。下面就给大家附上这个map方法的代码:
public <T> T mapper(final List<MondayColumnDTO> mondayColumnDTOs,T t) {
if (t != null && columnDtos != null || columnDtos.size() > 0) {
final Field[] fields = t.getClass().getDeclaredFields();
if (fields != null && fields.length > 0) {
for (final Field field : fields) {
final MondayMapper annotation = field.getAnnotation(MondayMapper.class);
try {
if (annotation != null) {
final String name = annotation.name();
if (StringUtils.hasText(name)) {
final Optional<MondayColumnDto> dtoOptional = columnDtos
.stream()
.filter(columnDto -> {
return name.equals(columnDto.getTitle());
})
.findFirst();
if (dtoOptional.isPresent()) {
field.setAccessible(true);
field.set(t, dtoOptional.get().getText());
}
}
}
} catch (final Exception e) {
log.error("failed convert MondayMapper {},entity {}", annotation, t);
}
}
}
}
return t;
}
这段代码的前提是先自定义一个注解来放在我们的entity的properties上面,注解的代码如下
package com.descours.cabaud.common.annotation;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MondayMapper {
String name() default "";
String type() default MondayColumnType.TEXT;
}
示例Entity代码如下
package com.descours.cabaud.domain;
import com.descours.cabaud.common.annotation.MondayColumnType;
import com.descours.cabaud.common.annotation.MondayMapper;
import javax.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.envers.Audited;
@Builder
@Entity
@Table(name = "commercial_invoice")
@AllArgsConstructor
@Data
@NoArgsConstructor
//@Audited
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class CommercialInvoice extends AbstractDCAuditingEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "date")
@MondayMapper(name = "Date", type = MondayColumnType.DATE)
private String date;
@Column(name = "client")
@MondayMapper(name = "Client", type = MondayColumnType.BOARD_RELATION)
private String client;
@Column(name = "cate_gory")
@MondayMapper(name = "Category", type = MondayColumnType.DROP_DOWN)
private String cateGory;
@Column(name = "total_price")
@MondayMapper(name = "Total Price")
private String totalPrice;
@Column(name = "currency")
@MondayMapper(name = "Currency", type = MondayColumnType.DROP_DOWN)
private String currency;
@Column(name = "remarks")
@MondayMapper(name = "Remarks", type = MondayColumnType.LONG_TEXT)
private String remarks;
}
下面的代码是另一个利用反射获取值并map的方法,也可以参考一下
public <T extends AbstractDCAuditingEntity> String generateUpdateQuery(
final T t,
final String boardId,
String parentMondayId,
String itemCode
) {
final Field[] fields = t.getClass().getDeclaredFields();
String updateCall = null;
if (t.getParentChild() != null) {
updateCall =
MondayAPITemplate.CREATE_SUB_ITEM
.replace(MondayAPITemplate.ITEMID, parentMondayId)
.replace(MondayAPITemplate.ITEMNAME, itemCode);
} else {
updateCall =
MondayAPITemplate.CHANGE_MULTIPLE_COLUMN_VALUES_UPDATE
.replace(MondayAPITemplate.BOARDID, t.getBoardId())
.replace(MondayAPITemplate.ITEMID, t.getItemId());
}
final StringBuffer cokumnValues = new StringBuffer("");
final List<MondayColumn> columns = mondayColumnRepository.findByBoardId(boardId);
if (fields != null && fields.length > 0 && columns != null && columns.size() > 0) {
for (final Field field : fields) {
final MondayMapper annotation = field.getAnnotation(MondayMapper.class);
try {
if (annotation != null) {
final String name = annotation.name();
final String type = annotation.type();
if (StringUtils.hasText(name)) {
final Optional<MondayColumn> mondayColumnOptional = columns
.stream()
.filter(mondayColumn -> {
return name.equals(mondayColumn.getTitle());
})
.findFirst();
if (mondayColumnOptional.isPresent()) {
field.setAccessible(true);
switch (type) {
case MondayColumnType.TEXT:
if (field.get(t) != null) {
final String value = (String) field.get(t);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(value)
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(",");
}
break;
case MondayColumnType.EMAIL:
if (field.get(t) != null) {
final String value = (String) field.get(t);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_EmailTemplateText)
.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(value)
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(",");
cokumnValues
.append(MondayAPITemplate.MondayAPI_EmailTemplateEmail)
.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(value)
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(MondayAPITemplate.MondayAPI_RightBrace)
.append(",");
}
break;
case MondayColumnType.DATE:
if (field.get(t) != null) {
final String value = (String) field.get(t);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues.append(MondayAPITemplate.MondayAPI_BoardDateTemplate);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(value)
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(MondayAPITemplate.MondayAPI_RightBrace)
.append(",");
}
break;
case MondayColumnType.LONG_TEXT:
if (field.get(t) != null) {
final String value = (String) field.get(t);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues.append(MondayAPITemplate.MondayAPI_EmailTemplateText);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(value)
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(MondayAPITemplate.MondayAPI_RightBrace)
.append(",");
}
break;
case MondayColumnType.LABEL:
if (field.get(t) != null) {
final String value = (String) field.get(t);
Integer resultValue = null;
if (MondayAPITemplate.MondayAPI_GroupValueLEVELOne.equals(value)) {
resultValue = MondayIdNumberOneZeroFive;
} else if (MondayAPITemplate.MondayAPI_GroupValueLEVELTwo.equals(value)) {
resultValue = MondayIdNumberThree;
} else if (MondayAPITemplate.MondayAPI_GroupValueLEVELThree.equals(value)) {
resultValue = MondayIdNumberOneFiveSix;
} else if (MondayAPITemplate.MondayAPI_InspectionStatusDone.equals(value)) {
resultValue = MondayIdNumberOne;
} else if (MondayAPITemplate.MondayAPI_InspectionStatusWorkOnIt.equals(value)) {
resultValue = MondayIdNumberZero;
} else if (MondayAPITemplate.MondayAPI_InspectionStatusStuck.equals(value)) {
resultValue = MondayIdNumberTwo;
}
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_LeftBrace)
.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues.append(resultValue).append(MondayAPITemplate.MondayAPI_RightBrace).append(",");
}
break;
case MondayColumnType.BOARD_RELATION:
if (field.get(t) != null) {
log.debug("the column id {}", mondayColumnOptional.get());
final String value = (String) field.get(t);
final List<String> ids = Arrays
.asList(value.split(","))
.stream()
.filter(id -> {
return StringUtils.hasText(id);
})
.collect(Collectors.toList());
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_BoardLink)
.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues.append(MondayAPITemplate.MondayAPI_middleBraceLeft);
for (int i = 0; i < ids.size(); i++) {
cokumnValues.append(
MondayAPITemplate.MondayAPI_BoardIdTemplate.replace(
MondayAPITemplate.ITEMID,
ids.get(i)
)
);
if (i < (ids.size() - 1)) {
cokumnValues.append(MondayAPITemplate.MondayAPI_Comma);
}
}
cokumnValues
.append(MondayAPITemplate.MondayAPI_middleBraceRight)
.append(MondayAPITemplate.MondayAPI_RightBrace)
.append(MondayAPITemplate.MondayAPI_Comma);
}
break;
case MondayColumnType.DROP_DOWN:
if (field.get(t) != null) {
log.debug("the column id {}", mondayColumnOptional.get());
final String value = (String) field.get(t);
Integer id = null;
id = getDropdownId(value, id);
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_DropDownTemplateLeft)
.append(id)
.append(MondayAPITemplate.MondayAPI_middleBraceRight)
.append(MondayAPITemplate.MondayAPI_RightBrace)
.append(",");
}
break;
case MondayColumnType.PEOPLE:
if (field.get(t) != null) {
log.debug("the column id {}", mondayColumnOptional.get());
final String value = (String) field.get(t);
final String[] userNames = value.split(",");
final List<MondayUser> users = new ArrayList<>();
for (final String userName : userNames) {
final Optional<MondayUser> mondayUserOptional = mondayUserRepository.findByName(
userName.trim()
);
if (mondayUserOptional.isPresent()) {
users.add(mondayUserOptional.get());
}
}
cokumnValues
.append(MondayAPITemplate.MondayAPI_Quotation)
.append(mondayColumnOptional.get().getColumnId())
.append(MondayAPITemplate.MondayAPI_Quotation);
cokumnValues.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues
.append(MondayAPITemplate.MondayAPI_PersonFirstHalf)
.append(MondayAPITemplate.MondayAPI_Colon);
cokumnValues.append(MondayAPITemplate.MondayAPI_middleBraceLeft);
for (int i = 0; i < users.size(); i++) {
cokumnValues.append(
MondayAPITemplate.MondayAPI_PersonIdTemplate.replace(
MondayAPITemplate.USERIS,
users.get(i).getMondayId().toString()
)
);
if (i < (users.size() - 1)) {
cokumnValues.append(MondayAPITemplate.MondayAPI_Comma);
}
}
cokumnValues
.append(MondayAPITemplate.MondayAPI_middleBraceRight)
.append(MondayAPITemplate.MondayAPI_RightBrace)
.append(MondayAPITemplate.MondayAPI_Comma);
}
break;
default:
log.error("UnSupport type {}", type);
}
}
}
}
} catch (final Exception e) {
log.error("failed convert update API annotation {},entity {}", annotation, t);
}
}
}
String coloumns = cokumnValues.toString();
if (coloumns.length() > 0) {
coloumns = coloumns.substring(0, coloumns.length() - 1);
}
return updateCall.replace(MondayAPITemplate.COLUMNVALUES, coloumns);
}