转换 java 源代码以将注释从 getter 移动到属性
Transforming java source code to move annotations from getters to properties
我有大约 300 个 JPA 实体,其中的 getter 带有持久性注释。我想找到一种方法将所有此类注释移至属性并删除所有 getter 和 setter。我为其中的大约 100 个 类 手动完成了此操作,但这是非常耗时且令人头脑麻木的工作。
我正在研究像 Spoon 这样的源代码转换工具,但仍然不确定它是否可以完成我需要它做的事情。
更具体地说,我该如何转换这段代码:
@Entity
@Table(name = "crm_ticket")
public class CrmTicket implements Serializable {
private static final long serialVersionUID = -902718555957517699L;
private CrmAccount crmAccount;
private ItsType subType;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "account")
public CrmAccount getCrmAccount() {
return crmAccount;
}
public void setCrmAccount(CrmAccount crmAccount) {
this.crmAccount = crmAccount;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sub_type")
public ItsType getSubType() {
return subType;
}
public void setSubType(ItsType type) {
this.subType = type;
}
}
为此:
@Entity
@Table(name = "crm_ticket")
@Data
public class CrmTicket implements Serializable {
private static final long serialVersionUID = -902718555957517699L;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "account")
private CrmAccount crmAccount;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sub_type")
private ItsType subType;
}
我最终使用了 Spoon。没有那么痛。我将他们的 Maven 插件配置到 运行 我的处理器,它转换了我的实体 类 的代码。然后我将生成的代码复制回我的项目并删除了插件配置。
这是我的处理器代码:
public class JpaAnnotationMover extends AbstractProcessor<CtMethod> {
Pattern p1 = Pattern.compile("return.*this\.(.*?)$");
Pattern p2 = Pattern.compile("return(.*?)$");
@Override
public boolean isToBeProcessed(CtMethod method) {
return isInEntity(method) && isAGetter(method) && hasOneStatement(method) && !isTransient(method);
}
@Override
public void process(CtMethod ctMethod) {
CtType parentClass = ctMethod.getParent(CtType.class);
String fieldName = getFieldName(ctMethod);
if (fieldName == null) {
log.warn(String.format("expected field name for %s not found.", ctMethod.getSimpleName()));
return;
}
CtField field = parentClass.getField(fieldName);
if (field == null) {
log.warn(String.format("Expected field %s not found.", fieldName));
return;
}
for (CtAnnotation<? extends Annotation> annotation : ctMethod.getAnnotations()) {
field.addAnnotation(annotation);
}
parentClass.removeMethod(ctMethod);
log.info(String.format("Processed method %s:%s", parentClass.getSimpleName(), ctMethod.getSimpleName()));
// find corresponding setter
String setterName = "set" + WordUtils.capitalize(fieldName);
@SuppressWarnings("unchecked") CtMethod setter = parentClass
.getMethod(getFactory().Type().createReference("void"), setterName, ctMethod.getType());
if (setter == null) {
log.warn(String.format("Unable to find setter for %s", fieldName));
return;
}
parentClass.removeMethod(setter);
if (!parentClass.hasAnnotation(Data.class)) {
parentClass.addAnnotation(getFactory().createAnnotation(getFactory().Type().createReference(Data.class)));
}
}
private Boolean isInEntity(CtMethod method) {
CtType parentClass = method.getParent(CtType.class);
return parentClass.hasAnnotation(Entity.class);
}
private Boolean isAGetter(CtMethod method) {
return method.getSimpleName().contains("get");
}
private Boolean hasOneStatement(CtMethod method) {
return method.getBody().getStatements().size() == 1;
}
private Boolean isTransient(CtMethod method) {
return method.hasAnnotation(Transient.class);
}
private String getFieldName(CtMethod method) {
String statement = method.getBody().getLastStatement().toString();
Matcher m = p1.matcher(statement);
Matcher m2 = p2.matcher(statement);
return m.matches() ? m.group(1).trim() : m2.matches() ? m2.group(1).trim() : null;
}
}
Spoon 很适合这个,您可以使用 aField。addAnnotation and aSetter.delete。
我有大约 300 个 JPA 实体,其中的 getter 带有持久性注释。我想找到一种方法将所有此类注释移至属性并删除所有 getter 和 setter。我为其中的大约 100 个 类 手动完成了此操作,但这是非常耗时且令人头脑麻木的工作。
我正在研究像 Spoon 这样的源代码转换工具,但仍然不确定它是否可以完成我需要它做的事情。
更具体地说,我该如何转换这段代码:
@Entity
@Table(name = "crm_ticket")
public class CrmTicket implements Serializable {
private static final long serialVersionUID = -902718555957517699L;
private CrmAccount crmAccount;
private ItsType subType;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "account")
public CrmAccount getCrmAccount() {
return crmAccount;
}
public void setCrmAccount(CrmAccount crmAccount) {
this.crmAccount = crmAccount;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sub_type")
public ItsType getSubType() {
return subType;
}
public void setSubType(ItsType type) {
this.subType = type;
}
}
为此:
@Entity
@Table(name = "crm_ticket")
@Data
public class CrmTicket implements Serializable {
private static final long serialVersionUID = -902718555957517699L;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "account")
private CrmAccount crmAccount;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sub_type")
private ItsType subType;
}
我最终使用了 Spoon。没有那么痛。我将他们的 Maven 插件配置到 运行 我的处理器,它转换了我的实体 类 的代码。然后我将生成的代码复制回我的项目并删除了插件配置。
这是我的处理器代码:
public class JpaAnnotationMover extends AbstractProcessor<CtMethod> {
Pattern p1 = Pattern.compile("return.*this\.(.*?)$");
Pattern p2 = Pattern.compile("return(.*?)$");
@Override
public boolean isToBeProcessed(CtMethod method) {
return isInEntity(method) && isAGetter(method) && hasOneStatement(method) && !isTransient(method);
}
@Override
public void process(CtMethod ctMethod) {
CtType parentClass = ctMethod.getParent(CtType.class);
String fieldName = getFieldName(ctMethod);
if (fieldName == null) {
log.warn(String.format("expected field name for %s not found.", ctMethod.getSimpleName()));
return;
}
CtField field = parentClass.getField(fieldName);
if (field == null) {
log.warn(String.format("Expected field %s not found.", fieldName));
return;
}
for (CtAnnotation<? extends Annotation> annotation : ctMethod.getAnnotations()) {
field.addAnnotation(annotation);
}
parentClass.removeMethod(ctMethod);
log.info(String.format("Processed method %s:%s", parentClass.getSimpleName(), ctMethod.getSimpleName()));
// find corresponding setter
String setterName = "set" + WordUtils.capitalize(fieldName);
@SuppressWarnings("unchecked") CtMethod setter = parentClass
.getMethod(getFactory().Type().createReference("void"), setterName, ctMethod.getType());
if (setter == null) {
log.warn(String.format("Unable to find setter for %s", fieldName));
return;
}
parentClass.removeMethod(setter);
if (!parentClass.hasAnnotation(Data.class)) {
parentClass.addAnnotation(getFactory().createAnnotation(getFactory().Type().createReference(Data.class)));
}
}
private Boolean isInEntity(CtMethod method) {
CtType parentClass = method.getParent(CtType.class);
return parentClass.hasAnnotation(Entity.class);
}
private Boolean isAGetter(CtMethod method) {
return method.getSimpleName().contains("get");
}
private Boolean hasOneStatement(CtMethod method) {
return method.getBody().getStatements().size() == 1;
}
private Boolean isTransient(CtMethod method) {
return method.hasAnnotation(Transient.class);
}
private String getFieldName(CtMethod method) {
String statement = method.getBody().getLastStatement().toString();
Matcher m = p1.matcher(statement);
Matcher m2 = p2.matcher(statement);
return m.matches() ? m.group(1).trim() : m2.matches() ? m2.group(1).trim() : null;
}
}
Spoon 很适合这个,您可以使用 aField。addAnnotation and aSetter.delete。