java - 在 spring boot 应用程序上禁用 open-in-view 时,Eclipse 或 Spring Boot 可以帮助我找到需要 Transactions 的方法吗?
问题描述
我正在开发一个相当新的 Spring Boot Java 应用程序,我没有意识到默认情况下启用了 spring jpa“open-in-view”设置。
我遇到了一些问题,禁用该设置最终成为最佳解决方案,但现在我遇到了几个我不小心依赖它的情况。
例如,我有一个未标记为 @Transactions 的 Service 类,在它返回到控制器之前循环遍历我的一个实体的延迟初始化子项。
现在这个函数按预期抛出了 LazyInitializationException,因为我不在事务中。
我还没有编写提供 100% 覆盖率的测试用例,Eclipse、Sprint 工具套件或 Spring Boot 运行时中是否有内置的东西可以生成一些报告,告诉我用 @Entity 注释的类何时具有功能在非事务性方法调用中对它们进行调用?
有没有其他方法可以尝试识别这一点,而不向我的应用程序添加 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);
}
}
}
推荐阅读
- rest - 如何通过 Delphi 在 Google Drive API 上调用创建权限
- webpack - webpack DllPlugin:WEBPACK_EXTERNAL_MODULE_dll_reference 未定义
- javascript - 你可以帮帮我吗。我怎样才能做出实时变化的价值?
- azure - 我可以从 Azure DevOps 向 Azure 中的 vm 运行 powershell 命令吗?
- angular - ngfor 中的 Angular 折叠按钮
- javascript - TypeScript 的字符串枚举或对象文字有(更好的)简写吗?
- c - 获取由 C 中的 AST 生成的树 ( String ) 输出的解决方案
- arrays - 查找数组中无序的对数
- c - C指针中的奇怪行为
- java - Java BigDecimal long 带十进制转换