2

我需要查找在其 equals() 方法中使用 JPA ID 属性的 JPA 持久类。例如,以下类将触发 PMD 规则违规:

@Entity
public class Foo
{
   @Id
   private long id;

   public boolean equals(Object o)
   {
      if (o.getClass().equals(Foo.class)) {
         Foo other = (Foo) o;
         return o.id == id;
      }
      return false;
   }
}

我知道如何让这个查询的各个部分工作,但不知道如何把它放在一起。因此,例如,我知道如何找到 JPA 持久类(假设使用 JPA 注释):

//ClassOrInterfaceDeclaration/../Annotation/MarkerAnnotation/Name[@Image='Entity']

我知道如何找到使用 JPA ID 注释注释的字段声明:

//FieldDeclaration[../Annotation/MarkerAnnotation/Name[@Image='Id']]

同样,我可以在 equals() 方法中找到一个引用名为“id”的字段的表达式:

//MethodDeclaration[
  ./MethodDeclarator[@Image='equals'] and
  ./MethodDeclarator/FormalParameters[1]/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[@Image='Object']
]
/Block//PrimaryExpression/PrimaryPrefix/Name[@Image='id']

我遇到的麻烦是使用表达式查找标有 @Id 注释的字段的名称,并在谓词中使用它来查找使用该字段的 equals() 方法中的行。

这是我对查询的最佳猜测,但它不返回任何节点:

//MethodDeclaration[
  ./MethodDeclarator[@Image='equals'] 
  and
  //MethodDeclarator[count(./FormalParameters)=1]
  and
  ./MethodDeclarator/FormalParameters[1]/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[@Image='Object']
]
/Block//PrimaryExpression/Name[
  @Image=ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
  ../Annotation/MarkerAnnotation/Name/@Image='Id']/VariableDeclarator/VariableDeclaratorId/@Image
]

前 7 行返回所有名称为“equals”的 MethodDeclarations,并采用单个“Object”参数。

下一部分选择该方法内的任何 PrimaryExpressions,其 Name 等于使用“Id”注释注释的字段的名称。有什么帮助吗?

4

1 回答 1

1

好的,我已经想通了......这是我想出的解决方案:

//MethodDeclaration[
  MethodDeclarator[
    count(FormalParameters/FormalParameter)=1 and
    @Image='equals' and
    FormalParameters/FormalParameter[1]/Type/ReferenceType/ClassOrInterfaceType[@Image='Object']
  ]
]
/Block//PrimaryExpression[
  PrimaryPrefix/@Image=
    ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
      ../Annotation/MarkerAnnotation/Name/@Image='Id'
    ] /VariableDeclarator/VariableDeclaratorId/@Image
  or
  PrimarySuffix/@Image=
    ancestor::ClassOrInterfaceDeclaration//FieldDeclaration[
      ../Annotation/MarkerAnnotation/Name/@Image='Id'
    ] /VariableDeclarator/VariableDeclaratorId/@Image
]

它似乎工作。

于 2013-02-05T15:42:53.327 回答