当前位置: 首页 > 知识库问答 >
问题:

ArchUnit中的AnyOf-谓词

冀嘉木
2023-03-14

我想测试所有Hibernate关联注释(@manytoone、@onetomany、@onetoone、@manytomany)是否使用fetch=fetchtype.lazy。这是有效的:

private static final Set<Class<? extends Annotation>> associations =
         Set.of(ManyToOne.class, OneToMany.class, OneToOne.class, ManyToMany.class);

@ArchTest
public static final ArchRule allEntityRelationsShouldBeLazy = fields().that()
      .areDeclaredInClassesThat().areAnnotatedWith(Entity.class)
      .and()
      .areAnnotatedWith(ManyToOne.class)
      .or().areAnnotatedWith(OneToMany.class)
      .or().areAnnotatedWith(OneToOne.class)
      .or().areAnnotatedWith(ManyToMany.class)
      // what I'd like: .areAnnotatedWith(Any.of(associations))
      .should()
      .notBeAnnotatedWith(new DescribedPredicate<>("FetchType.EAGER or undefined FetchType") {
         @Override
         public boolean apply(JavaAnnotation<?> input) {
            JavaClass rawType = input.getRawType();
            if (!rawType.isEquivalentTo(OneToOne.class)
            // what I'd like: if (!Any.of(associations).apply(input)) {
                  && !rawType.isEquivalentTo(OneToMany.class)
                  && !rawType.isEquivalentTo(ManyToOne.class)
                  && !rawType.isEquivalentTo(ManyToMany.class)) {
               // Filter again, because a field can contain multiple annotations.
               return false;
            }
            return input.get("fetch")
                  .transform(JavaEnumConstant.class::cast)
                  .transform(fetchType -> !FetchType.LAZY.name().equals(fetchType.name()))
                  .or(true);
         }
      });

我必须过滤两次,因为一个字段可以有几个注释,如下所示:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "otherEntity", referencedColumnName = "id")
private OtherEntity otherEntity;

共有1个答案

刘令
2023-03-14

您想要的可以用Java流操作构建:

import static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.lang.conditions.ArchPredicates.are;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields;
@ArchTest
ArchRule allEntityRelationsShouldBeLazy = fields().that()
    .areDeclaredInClassesThat().areAnnotatedWith(Entity.class)
    .and(are(annotatedWithAnyOf(associations)))
    .should().notBeAnnotatedWith(describe("FetchType.EAGER or undefined FetchType",
        input -> associations.stream().anyMatch(input.getRawType()::isEquivalentTo)
                 && input.get("fetch")
                     .transform(JavaEnumConstant.class::cast)
                     .transform(enumConst -> !FetchType.LAZY.name().equals(enumConst.name()))
                     .get()  // associations have a default fetch type
    ));
    
DescribedPredicate<CanBeAnnotated> annotatedWithAnyOf(Collection<Class<? extends Annotation>> annotations) {
    return annotations.stream()
            .map(CanBeAnnotated.Predicates::annotatedWith)
            .reduce(DescribedPredicate::or)
            .get();  // annotations must not be empty
}
 类似资料:
  • 在Swagger版本2.0中,什么等同于任何一个,请告诉我如何更新我的json文件,因为我想将我的文档从swagger 1.0升级到2.0。 谢谢你的帮助。

  • 环境是Java、Spring-boot、Hibernat、QueryDSL、MySQL。 我有表结构 艾碧索 更新 为了澄清起见,支持UI视图的DTO包含“casename”属性。它是在将域对象转换为DTO时在服务层创建的:

  • 我尝试使用swagger来描述JSON API。到目前为止,它看起来不错,但我无法弄清楚如何使用anyOf结构在JSON答案中定义不同对象类型的数组。 以下JSOn模式是有效的,它应该描述一组文章和视频JSON对象: 有没有可能在摇摆不定中使这项工作发挥作用?