java - 当在 Spring Boot 应用程序上禁用 open-in-view 时,Eclipse 或 Spring Boot 可以帮助我找到需要事务的方法吗?

标签 java spring eclipse spring-boot spring-tool-suite

我正在开发一个相当新的 Spring Boot Java 应用程序,我没有意识到默认情况下已启用 spring jpa“在 View 中打开”设置。

我遇到了一些问题,禁用该设置最终是最好的解决方案,但现在我遇到了一些我不小心依赖该设置的情况。

例如,我有一个未标记为 @Transactions 的 Service 类,在返回到 Controller 之前循环遍历我的实体之一的延迟初始化子级。

现在这个函数按照预期抛出 LazyInitializationException,因为我不在事务中。

我还没有编写提供 100% 覆盖率的测试用例,Eclipse、Sprint Tools Suite 或 Spring Boot 运行时中是否有任何内置内容可供我生成一些报告,以告诉我何时用 @ 注解的类实体在非事务方法调用中对其进行了函数调用?

还有其他方法可以尝试识别这一点,而不需要向我的应用程序添加 100% 代码覆盖率测试,或者仔细检查每个方法调用吗?

如果没有,那么我将处理测试用例。

感谢您的指导。

最佳答案

它并不完美,但我确实找到了一种使用 Reflections 库查找应用程序的大多数情况的方法。我将其作为 @SpringBootTest 测试用例运行,并一次修复一个错误。

@Test
public void testOne() throws NoSuchMethodException, SecurityException{
    Reflections reflections = new Reflections("my.base.package",
                        new SubTypesScanner(), 
                          new TypeAnnotationsScanner(),
                          new MemberUsageScanner());

    Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(javax.persistence.Entity.class);

    for( Class<?> c: annotated){
        log.debug(c.getSimpleName());
        for( Method m: c.getMethods()){
            if( m.getReturnType().isAnnotationPresent(Entity.class) ){
                checkTransactional(reflections,c, m, 0);
            }
        }
    }
   Assert.assertTrue(true);
}

public static void checkTransactional(Reflections reflections, Class<?> c, Method m, int depth) throws NoSuchMethodException, SecurityException{
    if( depth >64){
        throw new RuntimeException("No Transactional Method Found");
        //return;
    }
    String s = "--";
    Annotation t = null;

    Class<?>[] possibleAnnotations = {
            org.springframework.transaction.annotation.Transactional.class,
            javax.transaction.Transactional.class, 
    };

    Annotation[] annotations = m.getAnnotations();
    for( Annotation a: annotations){
        Class<?> aClass = a.annotationType();
        //// handle javax and spring Transactional
        if( aClass.getSimpleName().equals("Transactional")){
            t = a;
            s = "++";
            break;
        }
    }


    String prefix = "";
    for( int i = 0; i < depth; i++){
        prefix = prefix + s;
    }

    log.debug( prefix + " " + c.getCanonicalName() + ":" + m.getName());

    if( t != null ){
        log.trace("This is transactional");
        return;
    }

    Set<Member> callingMembers = reflections.getMethodUsage(m);
    if( callingMembers.size() == 0){
        log.error("Nothing calls this method, if it is a controller, we have a problem" + (c.isAnnotationPresent(Controller.class) || c.isAnnotationPresent(RestController.class)));
        if( (c.isAnnotationPresent(Controller.class) || c.isAnnotationPresent(RestController.class)) ){
            throw new RuntimeException("No transactional method found in call heirrchy before controller"); 
        }
    }
    for( Member usingMember: callingMembers){
        Class<?> callingClass = usingMember.getDeclaringClass();
        List<Method> callingMethods = new ArrayList<Method>();
        if( callingClass != c ){
            for( Method callingClassMethod: callingClass.getMethods()){
                if( callingClassMethod.getName().equals(usingMember.getName())){
                    callingMethods.add(callingClassMethod);
                }
            }   
        }
        if( callingMethods.size() > 2){
            log.error("Two methods call this, manually review");
            for( Method caller: callingMethods){
                log.debug( prefix + "!! " + c.getCanonicalName() + ":" + caller.getName() + ":" + caller.getParameterCount());
            }
            throw new RuntimeException("Two methods with same name ( overloading ) call this, manually review"); 

        }
        for( Method caller: callingMethods){
            checkTransactional(reflections, callingClass, caller, depth+1);
        }
    }
}

关于java - 当在 Spring Boot 应用程序上禁用 open-in-view 时,Eclipse 或 Spring Boot 可以帮助我找到需要事务的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58084679/

相关文章:

java - 你什么时候决定为你的对象使用访问者?

java - Eclipse 中的默认导入

c++ - Eclipse Papyrus UML 插件无法在类图中加载 C++ 构造型列表

java - 包含来自 Java Itext 的多个段落的 PDF

java - 如何在 debian buster 中允许对 java/tomcat 目录进行写访问

Java Spring MVC 返回多个值

java - 如何防止 Spring 中的计划重叠?

spring - 如何创建 URL slug 扩展?

java - 测试时如何在 Controller 内 Autowiring Spring bean?

eclipse - 如何优化Eclipse?