- AutoMapper增加配置信息convertGenerate,配置是否生成转换的接口,可以控制不生成接口;

- 增加注解 ReverseAutoMapping,提升反向配置映射关系的功能
- AutoMapping target属性默认可以不填,不填则取当前字段
This commit is contained in:
linpl 2023-02-27 19:26:48 +08:00
parent 3301b668d9
commit a22e35bb29
20 changed files with 458 additions and 66 deletions

View File

@ -9,6 +9,7 @@ Mapstruct Plus 是对 Mapstruct 框架的一个增强,只做增强,不做修
## 链接
- [Document](https://mapstruct.plus)
- [Mapstruct](https://mapstruct.org)
- [Gitee](https://gitee.com/linpeilie/mapstruct-plus)
- [Github](https://github.com/linpeilie/mapstruct-plus)
- [彻底干掉 BeanUtils最优雅的 Mapstruct 增强工具全新出炉](https://juejin.cn/post/7204307381688909882)

View File

@ -18,7 +18,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mapstruct.version>1.5.1.Final</mapstruct.version>
<mapstruct-plus.version>1.1.5</mapstruct-plus.version>
<mapstruct-plus.version>1.1.6</mapstruct-plus.version>
<lombok.version>1.18.22</lombok.version>
</properties>

View File

@ -12,8 +12,8 @@
<artifactId>spring-boot-3</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@ -55,8 +55,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<source>8</source>
<target>8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>

View File

@ -9,4 +9,8 @@ public class StringToListStringConverter {
return Arrays.asList(str.split(","));
}
public static String listStringToString(List<String> list) {
return String.join(",", list);
}
}

View File

@ -0,0 +1,48 @@
package io.github.linpeilie.model;
import io.github.linpeilie.StringToListStringConverter;
import io.github.linpeilie.annotations.AutoMapMapper;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMappers;
import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.annotations.ReverseAutoMapping;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import lombok.Data;
@Data
@AutoMappers({
@AutoMapper(target = OrderEntity.class, reverseConvertGenerate = false),
// @AutoMapper(target = OrderVO.class)
})
public class Order {
private String orderId;
@AutoMapping(expression = "java(java.lang.String.join(\",\", source.getGoods()))")
private List<String> goods;
@AutoMapping(numberFormat = "$0.00")
private BigDecimal orderPrice;
@AutoMapping(numberFormat = "$0.00")
private Integer goodsNum;
@AutoMapping(dateFormat = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime orderTime;
@AutoMapping(dateFormat = "yyyy_MM_dd HH:mm:ss")
private Date createTime;
@ReverseAutoMapping(target = "orderDate", dateFormat = "yyyy-MM-dd")
private String date;
@AutoMapping(source = "user.username")
private User user;
private Boolean payStatus;
}

View File

@ -0,0 +1,29 @@
package io.github.linpeilie.model;
import io.github.linpeilie.annotations.ReverseAutoMapping;
import java.time.LocalDate;
import lombok.Data;
import org.json.JSONObject;
@Data
public class OrderEntity {
private String orderId;
private String goods;
private String orderPrice;
private String goodsNum;
private String orderTime;
private String createTime;
private LocalDate orderDate;
private String user;
private String payStatus;
}

View File

@ -0,0 +1,41 @@
package io.github.linpeilie.model;
import io.github.linpeilie.StringToListStringConverter;
import io.github.linpeilie.annotations.AutoMapMapper;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.annotations.AutoMappings;
import io.github.linpeilie.annotations.ReverseAutoMapping;
import java.time.LocalDate;
import lombok.Data;
@Data
@AutoMapper(target = Order.class, uses = StringToListStringConverter.class, convertGenerate = false)
public class OrderVO {
private String orderId;
private String goods;
@ReverseAutoMapping(numberFormat = "$0.00")
private String orderPrice;
@ReverseAutoMapping(ignore = true)
private String goodsNum;
@ReverseAutoMapping(dateFormat = "yyyy-MM-dd HH:mm:ss")
private String orderTime;
@ReverseAutoMapping(dateFormat = "yyyy_MM_dd HHmmss")
private String createTime;
@ReverseAutoMapping(source = "date", dateFormat = "yyyy-MM-dd")
private LocalDate orderDate;
@ReverseAutoMapping(source = "user.username")
private String user;
@ReverseAutoMapping(defaultValue = "True")
private String payStatus;
}

View File

@ -10,6 +10,7 @@ import lombok.Data;
@Data
@AutoMappers({
@AutoMapper(target = UserDto.class),
@AutoMapper(target = UserDto.class),
@AutoMapper(target = UserVO.class)
})
@ -24,15 +25,15 @@ public class User {
private List<String> educationList;
@AutoMappings({
@AutoMapping(targetClass = UserDto.class, target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@AutoMapping(targetClass = UserVO.class, target = "birthday", ignore = true)
@AutoMapping(targetClass = UserDto.class, dateFormat = "yyyy-MM-dd HH:mm:ss"),
@AutoMapping(targetClass = UserVO.class, ignore = true)
})
private Date birthday;
@AutoMapping(targetClass = UserDto.class, target = "assets", numberFormat = "$0.00")
@AutoMapping(targetClass = UserDto.class, numberFormat = "$0.00")
private double assets;
@AutoMapping(target = "money", numberFormat = "$0.00")
@AutoMapping(numberFormat = "$0.00")
private double money;
@AutoMappings({

View File

@ -1,18 +1,25 @@
package io.github.linpeilie;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import io.github.linpeilie.model.Goods;
import io.github.linpeilie.model.GoodsDto;
import io.github.linpeilie.model.GoodsVo;
import io.github.linpeilie.model.MapModelA;
import io.github.linpeilie.model.Order;
import io.github.linpeilie.model.OrderVO;
import io.github.linpeilie.model.Sku;
import io.github.linpeilie.model.SysMenu;
import io.github.linpeilie.model.SysMenuVo;
import io.github.linpeilie.model.User;
import io.github.linpeilie.model.UserDto;
import io.github.linpeilie.model.UserVO;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@ -42,10 +49,10 @@ public class QuickStartTest {
mapModel1.put("mapModelB", mapModel2);
final MapModelA mapModelA = converter.convert(mapModel1, MapModelA.class);
System.out.println(mapModelA); // MapModelA(str=1jkf1ijkj3f, i1=111, l2=11231, mapModelB=MapModelB(date=2023-02-23 01:03:23))
System.out.println(
mapModelA); // MapModelA(str=1jkf1ijkj3f, i1=111, l2=11231, mapModelB=MapModelB(date=2023-02-23 01:03:23))
}
@Test
public void ueseTest() {
UserDto userDto = new UserDto();
@ -167,4 +174,32 @@ public class QuickStartTest {
System.out.println(goodsVo);
}
@Test
public void reverseMappingTest() {
Order order = new Order();
order.setOrderId("394bcab38052404ab404c791cb975596");
order.setGoods(Arrays.asList("Apple", "Phone"));
order.setOrderPrice(BigDecimal.valueOf(123.3421));
order.setGoodsNum(32);
order.setOrderTime(LocalDateTime.of(2023, 1, 3, 12, 23, 1));
order.setCreateTime(DateUtil.parseDateTime("2023-01-03 11:06:01"));
order.setDate("2022-03-01");
User user = new User();
user.setUsername("Jack");
order.setUser(user);
OrderVO orderVO = converter.convert(order, OrderVO.class);
System.out.println(orderVO);
Assert.equals(orderVO.getOrderId(), "394bcab38052404ab404c791cb975596");
Assert.equals(orderVO.getGoods(), "Apple,Phone");
Assert.equals(orderVO.getOrderPrice(), "$123.34");
Assert.isNull(orderVO.getGoodsNum());
Assert.equals(orderVO.getOrderTime(), "2023-01-03 12:23:01");
Assert.equals(orderVO.getCreateTime(), "2023_01_03 110601");
Assert.equals(orderVO.getOrderDate(), LocalDate.parse("2022-03-01", DateTimeFormatter.ofPattern("yyyy-MM-dd")));
Assert.equals(orderVO.getUser(), "Jack");
Assert.equals(orderVO.getPayStatus(), "True");
}
}

View File

@ -1,5 +1,7 @@
package io.github.linpeilie.processor;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.squareup.javapoet.ClassName;
import io.github.linpeilie.annotations.AutoMapMapper;
import io.github.linpeilie.annotations.AutoMapper;
@ -8,6 +10,8 @@ import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.annotations.AutoMappings;
import io.github.linpeilie.annotations.ComponentModelConfig;
import io.github.linpeilie.annotations.MapperConfig;
import io.github.linpeilie.annotations.ReverseAutoMapping;
import io.github.linpeilie.annotations.ReverseAutoMappings;
import io.github.linpeilie.processor.generator.AutoMapperGenerator;
import io.github.linpeilie.processor.generator.DefaultAdapterMapperGenerator;
import io.github.linpeilie.processor.generator.MapperConfigGenerator;
@ -43,6 +47,7 @@ import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.MappingConstants;
import org.mapstruct.ReportingPolicy;
import static io.github.linpeilie.processor.Constants.AUTO_MAPPERS_ANNOTATION;
import static io.github.linpeilie.processor.Constants.AUTO_MAPPER_ANNOTATION;
@ -69,6 +74,8 @@ public class AutoMapperProcessor extends AbstractProcessor {
private final List<AutoMapperMetadata> mapperList = new ArrayList<>();
private final Set<String> mapperSet = new HashSet<>();
public AutoMapperProcessor() {
this.mapperGenerator = new AutoMapperGenerator();
this.mapperConfigGenerator = new MapperConfigGenerator();
@ -216,19 +223,17 @@ public class AutoMapperProcessor extends AbstractProcessor {
}
private void generateMapper() {
final Set<String> mapperSet = new HashSet<>();
// 去重
mapperList.removeIf(mapper -> !mapperSet.add(mapper.mapperName()));
List<AutoMapperMetadata> reverseMapperMetadataList = new ArrayList<>();
mapperList.forEach(autoMapperMetadata -> {
if (!autoMapperMetadata.isReverseConvertGenerate()) {
return;
}
boolean defineReverseMapping = CollectionUtil.isNotEmpty(autoMapperMetadata.getFieldReverseMappingList());
final AutoMapperMetadata reverseMapperMetadata = reverseMapper(autoMapperMetadata);
if (!mapperSet.add(reverseMapperMetadata.mapperName())) {
if (defineReverseMapping) {
addMapper(reverseMapperMetadata);
} else if (!mapperSet.add(reverseMapperMetadata.mapperName())) {
return;
}
reverseMapperMetadataList.add(reverseMapperMetadata);
@ -237,6 +242,9 @@ public class AutoMapperProcessor extends AbstractProcessor {
mapperList.addAll(reverseMapperMetadataList);
mapperList.forEach(metadata -> {
if (!metadata.isConvertGenerate()) {
return;
}
this.writeAutoMapperClassFile(metadata);
addAdapterMethod(metadata.getSourceClassName(), metadata.getTargetClassName(), metadata.mapperClass());
});
@ -248,23 +256,25 @@ public class AutoMapperProcessor extends AbstractProcessor {
}
private AutoMapperMetadata reverseMapper(AutoMapperMetadata autoMapperMetadata) {
AutoMapperMetadata reverseMapperMetadata = new AutoMapperMetadata();
reverseMapperMetadata.setSourceClassName(autoMapperMetadata.getTargetClassName());
reverseMapperMetadata.setTargetClassName(autoMapperMetadata.getSourceClassName());
reverseMapperMetadata.setSuperClass(autoMapperMetadata.getSuperClass());
reverseMapperMetadata.setSuperGenerics(
new ClassName[] {reverseMapperMetadata.getSourceClassName(), reverseMapperMetadata.getTargetClassName()});
AutoMapperMetadata reverseMapperMetadata = initAutoMapperMetadata(
autoMapperMetadata.getTargetClassName(), autoMapperMetadata.getSourceClassName());
reverseMapperMetadata.setConvertGenerate(autoMapperMetadata.isReverseConvertGenerate());
reverseMapperMetadata.setUsesClassNameList(autoMapperMetadata.getUsesClassNameList());
reverseMapperMetadata.setMapstructConfigClass(
ClassName.get(AutoMapperProperties.getConfigPackage(), AutoMapperProperties.getConfigClassName()));
// 需要继承的属性
final List<AutoMappingMetadata> fieldMetadataList =
autoMapperMetadata.getFieldMappingList().stream().map(fieldMapping -> {
final AutoMappingMetadata autoMappingMetadata = new AutoMappingMetadata();
autoMappingMetadata.setSource(fieldMapping.getTarget());
autoMappingMetadata.setTarget(fieldMapping.getSource());
return autoMappingMetadata;
}).collect(Collectors.toList());
reverseMapperMetadata.setFieldMappingList(fieldMetadataList);
if (CollectionUtil.isNotEmpty(autoMapperMetadata.getFieldReverseMappingList())) {
reverseMapperMetadata.setFieldMappingList(autoMapperMetadata.getFieldReverseMappingList());
} else {
// 需要继承的属性
final List<AutoMappingMetadata> fieldMetadataList =
autoMapperMetadata.getFieldMappingList().stream().map(fieldMapping -> {
final AutoMappingMetadata autoMappingMetadata = new AutoMappingMetadata();
autoMappingMetadata.setSource(fieldMapping.getTarget());
autoMappingMetadata.setTarget(fieldMapping.getSource());
return autoMappingMetadata;
}).collect(Collectors.toList());
reverseMapperMetadata.setFieldMappingList(fieldMetadataList);
}
return reverseMapperMetadata;
}
@ -293,12 +303,32 @@ public class AutoMapperProcessor extends AbstractProcessor {
mapMethodMap.put(adapterMapMethodMetadata.getMethodName(), adapterMapMethodMetadata);
}
private AutoMapperMetadata initAutoMapperMetadata(ClassName source, ClassName target) {
AutoMapperMetadata metadata = new AutoMapperMetadata();
metadata.setSourceClassName(source);
metadata.setTargetClassName(target);
metadata.setSuperClass(ClassName.get("io.github.linpeilie", "BaseMapper"));
metadata.setSuperGenerics(new ClassName[] {source, target});
metadata.setMapstructConfigClass(
ClassName.get(AutoMapperProperties.getConfigPackage(), AutoMapperProperties.getConfigClassName()));
return metadata;
}
private List<AutoMapperMetadata> buildAutoMapperMetadataByAutoMappers(final Element ele) {
final AutoMappers autoMappers = ele.getAnnotation(AutoMappers.class);
if (autoMappers == null) {
return null;
}
Set<String> targetClassNames = new HashSet<>();
return Arrays.stream(autoMappers.value())
.filter(autoMapper -> {
ClassName className = transToClassName(autoMapper::target);
if (className == null) {
return false;
}
return targetClassNames.add(className.reflectionName());
})
.map(autoMapper -> buildAutoMapperMetadata(autoMapper, ele))
.collect(Collectors.toList());
}
@ -311,6 +341,31 @@ public class AutoMapperProcessor extends AbstractProcessor {
return buildAutoMapperMetadata(autoMapperAnnotation, ele);
}
private boolean hasReverseAutoMapping(Element ele) {
TypeElement typeElement = (TypeElement) ele;
if (!typeElement.getKind().isClass()) {
return false;
}
return typeElement.getEnclosedElements()
.stream().anyMatch(e -> {
if (e.getKind() != ElementKind.FIELD) {
return false;
}
return e.getAnnotation(ReverseAutoMapping.class) != null
|| e.getAnnotation(ReverseAutoMappings.class) != null;
});
}
private boolean isTargetFieldMapping(ClassName target, AutoMappingMetadata mappingMetadata) {
if (MAPPING_DEFAULT_TARGET.reflectionName().contentEquals(mappingMetadata.getTargetClass().reflectionName())) {
return true;
}
if (target.reflectionName().contentEquals(mappingMetadata.getTargetClass().reflectionName())) {
return true;
}
return false;
}
private AutoMapperMetadata buildAutoMapperMetadata(final AutoMapper autoMapper, final Element ele) {
ClassName source = ClassName.get((TypeElement) ele);
ClassName target = transToClassName(autoMapper::target);
@ -319,31 +374,85 @@ public class AutoMapperProcessor extends AbstractProcessor {
}
List<ClassName> uses = transToClassNameList(autoMapper::uses);
List<AutoMappingMetadata> autoMappingMetadataList = buildFieldMappingMetadata((TypeElement) ele);
autoMappingMetadataList.removeIf(mappingMetadata -> {
if (MAPPING_DEFAULT_TARGET.reflectionName()
.contentEquals(mappingMetadata.getTargetClass().reflectionName())) {
return false;
}
if (target.reflectionName().contentEquals(mappingMetadata.getTargetClass().reflectionName())) {
return false;
}
return true;
});
autoMappingMetadataList.removeIf(mappingMetadata -> !isTargetFieldMapping(target, mappingMetadata));
AutoMapperMetadata metadata = new AutoMapperMetadata();
List<AutoMappingMetadata> reverseMappingMetadataList = buildFieldReverseMappingMetadata((TypeElement) ele);
reverseMappingMetadataList.removeIf(mappingMetadata -> !isTargetFieldMapping(target, mappingMetadata));
AutoMapperMetadata metadata = initAutoMapperMetadata(source, target);
metadata.setSourceClassName(source);
metadata.setTargetClassName(target);
metadata.setUsesClassNameList(uses);
metadata.setFieldMappingList(autoMappingMetadataList);
metadata.setSuperClass(ClassName.get("io.github.linpeilie", "BaseMapper"));
metadata.setSuperGenerics(new ClassName[] {source, target});
metadata.setMapstructConfigClass(
ClassName.get(AutoMapperProperties.getConfigPackage(), AutoMapperProperties.getConfigClassName()));
metadata.setFieldReverseMappingList(reverseMappingMetadataList);
metadata.setConvertGenerate(autoMapper.convertGenerate());
metadata.setReverseConvertGenerate(autoMapper.reverseConvertGenerate());
addMapper(metadata);
return metadata;
}
private List<AutoMappingMetadata> buildFieldReverseMappingMetadata(final TypeElement ele) {
List<AutoMappingMetadata> list = new ArrayList<>();
if (!ele.getKind().isClass()) {
return list;
}
for (Element field : ele.getEnclosedElements()) {
if (field.getKind() != ElementKind.FIELD) {
continue;
}
ReverseAutoMapping reverseAutoMapping = field.getAnnotation(ReverseAutoMapping.class);
if (reverseAutoMapping != null) {
list.add(buildAutoMappingMetadata(reverseAutoMapping, field, ele));
}
ReverseAutoMappings reverseAutoMappings = field.getAnnotation(ReverseAutoMappings.class);
if (reverseAutoMappings != null) {
for (ReverseAutoMapping mapping : reverseAutoMappings.value()) {
list.add(buildAutoMappingMetadata(mapping, field, ele));
}
}
}
list.removeIf(Objects::isNull);
return list;
}
private AutoMappingMetadata buildAutoMappingMetadata(ReverseAutoMapping reverseAutoMapping,
Element ele,
TypeElement type) {
ClassName targetClass = transToClassName(reverseAutoMapping::targetClass);
if (targetClass == null) {
return null;
}
AutoMappingMetadata metadata = new AutoMappingMetadata();
if (StrUtil.isNotEmpty(reverseAutoMapping.source())) {
metadata.setSource(reverseAutoMapping.source());
} else {
metadata.setSource(ele.getSimpleName().toString());
}
if (StrUtil.isNotEmpty(reverseAutoMapping.target())) {
metadata.setTarget(reverseAutoMapping.target());
} else {
metadata.setTarget(ele.getSimpleName().toString());
}
metadata.setTargetClass(targetClass);
metadata.setDefaultValue(reverseAutoMapping.defaultValue());
metadata.setIgnore(reverseAutoMapping.ignore());
metadata.setExpression(reverseAutoMapping.expression());
metadata.setDateFormat(reverseAutoMapping.dateFormat());
metadata.setNumberFormat(reverseAutoMapping.numberFormat());
return metadata;
}
private void addMapper(AutoMapperMetadata metadata) {
if (!mapperSet.add(metadata.mapperName())) {
throw new DuplicateMapperException("An exception occurred to generate " + metadata.mapperName()
+ ", check the mapping configuration for "
+ metadata.getSourceClassName().reflectionName()
+ " or " + metadata.getTargetClassName().reflectionName());
}
}
private List<AutoMappingMetadata> buildFieldMappingMetadata(final TypeElement autoMapperEle) {
List<AutoMappingMetadata> list = new ArrayList<>();
@ -378,13 +487,17 @@ public class AutoMapperProcessor extends AbstractProcessor {
}
AutoMappingMetadata metadata = new AutoMappingMetadata();
if (autoMapping.source() != null && !autoMapping.source().isEmpty()) {
if (StrUtil.isNotEmpty(autoMapping.source())) {
metadata.setSource(autoMapping.source());
} else {
metadata.setSource(ele.getSimpleName().toString());
}
if (StrUtil.isNotEmpty(autoMapping.target())) {
metadata.setTarget(autoMapping.target());
} else {
metadata.setTarget(ele.getSimpleName().toString());
}
metadata.setTargetClass(targetClass);
metadata.setTarget(autoMapping.target());
metadata.setDefaultValue(autoMapping.defaultValue());
metadata.setIgnore(autoMapping.ignore());
metadata.setExpression(autoMapping.expression());

View File

@ -0,0 +1,8 @@
package io.github.linpeilie.processor;
public class DuplicateMapperException extends RuntimeException {
public DuplicateMapperException(final String message) {
super(message);
}
}

View File

@ -23,6 +23,7 @@ import java.util.Optional;
import java.util.stream.Collectors;
import javax.lang.model.element.Modifier;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.ReportingPolicy;
import static io.github.linpeilie.processor.Constants.*;
@ -76,13 +77,16 @@ public class AutoMapperGenerator {
.addMember("target", CodeBlock.builder().add("$S", autoMappingMetadata.getTarget()).build())
.addMember("ignore", CodeBlock.builder().add(String.valueOf(autoMappingMetadata.isIgnore())).build());
if (StrUtil.isNotEmpty(autoMappingMetadata.getDateFormat())) {
builder.addMember("dateFormat", CodeBlock.builder().add("$S", autoMappingMetadata.getDateFormat()).build());
builder.addMember("dateFormat",
CodeBlock.builder().add("$S", autoMappingMetadata.getDateFormat()).build());
}
if (StrUtil.isNotEmpty(autoMappingMetadata.getNumberFormat())) {
builder.addMember("numberFormat", CodeBlock.builder().add("$S", autoMappingMetadata.getNumberFormat()).build());
builder.addMember("numberFormat",
CodeBlock.builder().add("$S", autoMappingMetadata.getNumberFormat()).build());
}
if (StrUtil.isNotEmpty(autoMappingMetadata.getDefaultValue())) {
builder.addMember("defaultValue", CodeBlock.builder().add("$S", autoMappingMetadata.getDefaultValue()).build());
builder.addMember("defaultValue",
CodeBlock.builder().add("$S", autoMappingMetadata.getDefaultValue()).build());
}
if (StringUtils.isNoneEmpty(autoMappingMetadata.getExpression())) {
builder.addMember("expression",

View File

@ -1,24 +1,28 @@
package io.github.linpeilie.processor.metadata;
import com.squareup.javapoet.ClassName;
import io.github.linpeilie.processor.AutoMapperProperties;
import java.util.List;
import org.mapstruct.ReportingPolicy;
public class AutoMapperMetadata extends AbstractMapperMetadata {
private ClassName targetClassName;
private List<ClassName> usesClassNameList;
private List<AutoMappingMetadata> fieldMappingList;
private List<AutoMappingMetadata> fieldReverseMappingList;
private ClassName superClass;
private ClassName[] superGenerics;
private ClassName mapstructConfigClass;
private boolean convertGenerate;
private boolean reverseConvertGenerate;
public String mapperName() {
@ -83,4 +87,20 @@ public class AutoMapperMetadata extends AbstractMapperMetadata {
public void setReverseConvertGenerate(final boolean reverseConvertGenerate) {
this.reverseConvertGenerate = reverseConvertGenerate;
}
public List<AutoMappingMetadata> getFieldReverseMappingList() {
return fieldReverseMappingList;
}
public void setFieldReverseMappingList(final List<AutoMappingMetadata> fieldReverseMappingList) {
this.fieldReverseMappingList = fieldReverseMappingList;
}
public boolean isConvertGenerate() {
return convertGenerate;
}
public void setConvertGenerate(final boolean convertGenerate) {
this.convertGenerate = convertGenerate;
}
}

View File

@ -5,6 +5,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author linpl
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface AutoMapper {
@ -13,11 +16,17 @@ public @interface AutoMapper {
Class<?>[] uses() default {};
/**
* 是否生成转换的接口当只想生成反向接口时可以指定当前属性为 {@code false}
*
* @return {@code true} 生成类型转换的接口 {@code false} 不生成类型转换的接口
*/
boolean convertGenerate() default true;
/**
* 是否生成反向转换的接口
*
* @return true : 生成反向转换的接口
* false : 不生成反向转换的接口
* @return true : 生成反向转换的接口 false : 不生成反向转换的接口
*/
boolean reverseConvertGenerate() default true;

View File

@ -16,10 +16,11 @@ public @interface AutoMapping {
* 来源默认取当前字段名称
* - 可以是当前类中的属性名
* - 也可以是属性名.属性名例如address.city.name
* @return 当前类中的属性
*/
String source() default "";
String target();
String target() default "";
String dateFormat() default "";
@ -31,6 +32,7 @@ public @interface AutoMapping {
/**
* 默认值
* @return 当源属性为null时设置的默认值
*/
String defaultValue() default "";

View File

@ -18,6 +18,7 @@ public @interface MapperConfig {
/**
* 所生成的 Mapper 接口的包
* @return Mapper 接口自动生成后的包名如果为空则默认生成在要转换的类同包下
*/
String mapperPackage() default "";

View File

@ -0,0 +1,66 @@
package io.github.linpeilie.annotations;
import io.github.linpeilie.DefaultMapping;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 由目标类生成当前类的配置
* <p>
* {@link AutoMapper} 的生成规则是由配置注解的当前类生成与目标类之间的转换接口所以其内部字段中的 {@link AutoMapping} 都是基于该条件来配置的
* 虽然默认情况下会生成目标类到当前类的转换但如果自定义配置的话仍需要到目标类上面进行配置
* </p>
* <p>
* 但现实情况中可能会出现目标类不能或者不建议增加配置注解所以这里提供一种在一种类上面自定义配置两个类转换的方式 如果需要配置由目标类转换为配置注解的当前类具体转换逻辑的话可以使用当前注解
* </p>
* <p>
* <strong>需要注意的是如果在当前类中配置了该注解信息则在目标类中不能够再定义与该类转换相关的注解例如{@code AutoMapper}{@code AutoMapping}</strong>
* </p>
*
* @author linpl
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface ReverseAutoMapping {
Class<?> targetClass() default DefaultMapping.class;
/**
* 来源默认取当前字段名称
* <ul><li>可以是当前类中的属性名</li>
* <li>也可以是属性名.属性名例如address.city.name</li></ul>
* <strong>这里的来源指的是目标类中的字段信息</strong>
*
* @return 目标类中的属性
*/
String source() default "";
/**
* 目标属性默认取当前字段名称
* <ul>
* <li>可以是当前类中的属性名</li>
* <li>也可以是属性名.属性名例如address.city.name</li>
* </ul>
*
* @return 当前类中的属性
*/
String target() default "";
String dateFormat() default "";
String numberFormat() default "";
String expression() default "";
boolean ignore() default false;
/**
* 默认值
*
* @return 当来源属性为null时所设置的默认值
*/
String defaultValue() default "";
}

View File

@ -0,0 +1,14 @@
package io.github.linpeilie.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface ReverseAutoMappings {
ReverseAutoMapping[] value();
}

View File

@ -38,10 +38,6 @@ public class MapObjectConvert {
return Convert.toDouble(obj);
}
public static Number objToNumber(Object obj) {
return Convert.toNumber(obj);
}
public static Boolean objToBoolean(Object obj) {
return Convert.toBool(obj);
}

View File

@ -9,7 +9,7 @@
<packaging>pom</packaging>
<version>${mapstruct-plus.version}</version>
<name>Mapstruct Plus</name>
<description>mapstruct增工具包</description>
<description>mapstruct增工具包</description>
<modules>
<module>mapstruct-plus</module>
<module>mapstruct-plus-spring-boot-starter</module>
@ -17,11 +17,11 @@
</modules>
<properties>
<mapstruct-plus.version>1.1.5</mapstruct-plus.version>
<mapstruct-plus.version>1.1.6</mapstruct-plus.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mapstruct.version>1.5.1.Final</mapstruct.version>
<mapstruct.version>1.5.3.Final</mapstruct.version>
<hutool.version>5.8.9</hutool.version>
<projectUrl>https://github.com/linpeilie/mapstruct-plus.git</projectUrl>
</properties>