C++ Range - for_each4:invoke

本文详细分析了C++中的invoke函数,包括operator ()、CPP_ret、meta::invoke、enable_if_t及其在for_each中的应用。CPP_ret模拟了概念,只有在特定条件下才返回指定类型。meta::invoke用于元编程中调用函数。同时介绍了enable_if_t的用法,它将enable标志放在了类型定义之后。最后,文章讨论了coerce的作用以及invoke在不同情况下的调用方式。

invoke

在for_each2节中讲到for_each的调用函数invoke,在第for_each3节中,分析了一个关键宏CPP_auto_fun的实现,发现原来的代码中,Eric的例子返回值应该需要auto,给他提了patch. 这节回到invoke的分析。

operator ()

  template<class F, class T, class T1, class... Args>
  constexpr auto CPP_auto_fun(operator())(F T::*f, T1&& t1, Args&&... args)(const)
  (
      return (invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f)
          (static_cast<Args&&>(args)...)
  )

经过CPP_auto_fun的扩展

  template<class F, class T, class T1, class... Args>
  constexpr auto operator() (F T::*f, T1&& t1, Args&&... args) 
  		const noexcept(noexcept(decltype((invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f) (static_cast<Args&&>(args)...))((invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f) (static_cast<Args&&>(args)...))))
  		 -> decltype((invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f) (static_cast<Args&&>(args)...)) 
{ 
·  return ((invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f) (static_cast<Args&&>(args)...)); 
}

这个的关键是coerce的作用; 要分析coerce 先要分析两个宏定义:

CPP_ret

#if CPP_CXX_CONCEPTS
#define CPP_ret(...)                                                            \
    __VA_ARGS__ CPP_PP_EXPAND                                                   \
    /**/
#else
#define CPP_ret                                                                 \
    CPP_broken_friend_ret                                                       \
    /**/
#endif

定义concepts的时候,CPP_ret 被扩展为 arg, CPP_PP_EXPAND。 CPP_PP_EXPAND的定义为:

#define CPP_PP_EXPAND(...) __VA_ARGS__

相当于CPP_ret(X)(Y) 变成了X Y; 

在没有定义concepts的时候:

CPP_broken_friend_ret的定义为:

#define CPP_broken_friend_ret(...)                                              \
    ::concepts::detail::enable_if_t<__VA_ARGS__,                                \
    CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_                                          \
    /**/
#define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_(...)                                 \
    CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(CPP_PP_CAT(                            \
        CPP_TEMPLATE_AUX_2_, __VA_ARGS__))                                      \
    /**/
#define CPP_TEMPLATE_AUX_2_requires
#define CPP_BROKEN_FRIEND_RETURN_TYPE_AUX_3_(...)                               \
    static_cast<bool>(__VA_ARGS__) || CPP_false(::concepts::detail::xNil{})>    \

以CPP_ret(T1 &&)(requires DerivedFrom<detail::decay_t, T>) 为例,
扩展完是:

::concepts::detail::enable_if_t<T1 &&,  static_cast<bool>( DerivedFrom<detail::decay_t<T1>, T>) || CPP_false(::concepts::detail::xNil{})>

总结:CPP_ret模拟concept,只有在后面require满足的情况下,才返回前面指定的类型T1 &&。

meta::invoke

    template <META_TYPE_CONSTRAINT(Invocable) Fn, typename... Args>
    using invoke = typename Fn::template invoke<Args...>;

元编程模拟invoke函数,相当于把Args传给Fn里面的invoke。

enable_if_t

        template<typename...>
        struct identity
        {
            template<typename T>
            using invoke = T;
        };

        template<typename T, bool Enable>
        using enable_if_t = meta::invoke<identity<std::enable_if_t<Enable>>, T>;

作者改写了std的enable_if_t函数,把enable的标识放在了后面。
结合上面invoke的分析,这个函数的作用是将identity中的invoke赋值为T。

CPP_def

        CPP_def
        (
            template(typename T, typename U)
            concept WeaklyEqualityComparableWith_,
                requires (detail::as_cref_t<T> t, detail::as_cref_t<U> u)
                (
                    (t == u) ? 1 : 0,
                    (t != u) ? 1 : 0,
                    (u == t) ? 1 : 0,
                    (u != t) ? 1 : 0
                )
        );     

结合上面的代码分析,最终解析成:

struct WeaklyEqualityComparableWith_Concept { 
  using Concept = WeaklyEqualityComparableWith_Concept;

  template<typename T, typename U>
  static auto Requires_ (detail::as_cref_t<T> t, detail::as_cref_t<U> u) -> ::concepts::detail::enable_if_t<int, static_cast<bool>
      (::concepts::detail::requires_ <decltype((t == u) ? 1 : 0, (t != u) ? 1 : 0, (u == t) ? 1 : 0, (u != t) ? 1 : 0, void())>() )>;

  template<typename T, typename U> struct Eval 
  { 
    template<typename C_ = Concept> 
    static constexpr decltype( &C_::template Requires_<T, U>, true)  impl(int) noexcept 
    { 
      return true; 
    } 
    
    static constexpr bool impl(long) noexcept { 
      return false; 
    }
    
    explicit constexpr operator bool() const noexcept 
    { 
      return Eval::impl(0); 
    } 
    
    constexpr auto operator!() const noexcept 
    { 
      return ::concepts::detail::Not<Eval>{}; 
    }
    
    template<typename That> constexpr auto operator&&(That) const noexcept 
    { 
      return ::concepts::detail::And<Eval, That>{}; 
    } 
  }; 
}; 


template<typename T, typename U> constexpr bool WeaklyEqualityComparableWith_ = (bool)WeaklyEqualityComparableWith_Concept::Eval<T, U>{}; 
namespace lazy { 
  template<typename T, typename U> 
  constexpr auto WeaklyEqualityComparableWith_ = WeaklyEqualityComparableWith_Concept::Eval<T, U>{}; 
} 
 
namespace defer { 
  using namespace lazy; 
}
using _concepts_int_ = int;		

总结:
CPP_def相当于定义了一个concepts。如上面的例子,如果不满足条件,返回WeaklyEqualityComparableWith_ 为false;如果满足条件返回WeaklyEqualityComparableWith_ 为true。

coerce

看一个简单的

    struct invoke_fn
    {
    private:
        template<class, class T1>
        constexpr static decltype(auto) CPP_fun(coerce)(T1 && t1, long)( // 如果t1可以解引用,返回解引用后的值,
                                                                                                                // 这样允许invoke的时候,传入对象的指针
            noexcept(noexcept(*static_cast<T1 &&>(t1)))                  //
            requires detail::Dereferenceable_<T1>)
        {
            return *static_cast<T1 &&>(t1);
        }

        template<class T, class T1>
        constexpr static auto coerce(T1 && t1, int) noexcept -> CPP_ret(T1 &&)( // 这个允许基类的指针,传入子类的对象
            requires DerivedFrom<detail::decay_t<T1>, T>)
        {
            return static_cast<T1 &&>(t1);
        }

        template<class, class T1>
        constexpr static decltype(auto) CPP_fun(coerce)(T1 && t1, int)( // 如果是reference_wrapper_v, 先get value
            noexcept(true) //
            requires detail::is_reference_wrapper_v<detail::decay_t<T1>>)
        {
            return static_cast<T1 &&>(t1).get();
        }

    public:
        // clang-format off
        template<class F, class T, class T1, class... Args>
        constexpr auto CPP_auto_fun(operator())(F T::*f, T1&& t1, Args&&... args)(const)  // 允许通过类的指针调用有参数的情况
        (
            return (invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f)
                (static_cast<Args&&>(args)...)
        )

        template<class D, class T, class T1>
        constexpr auto CPP_auto_fun(operator())(D T::*f, T1&& t1)(const)  // 允许通过类的指针调用类的变量
        (
            return invoke_fn::coerce<T>(static_cast<T1&&>(t1), 0).*f
        )

        template<class F, class... Args>
        CPP_PP_IIF(RANGES_CONSTEXPR_INVOKE)(CPP_PP_EXPAND, CPP_PP_EAT)(constexpr)
        auto CPP_auto_fun(operator())(F&& f, Args&&... args)(const)    // 允许function + arg 的形式调用
        (
            return static_cast<F&&>(f)(static_cast<Args&&>(args)...)
        )
        // clang-format on
    };

在C++中,函数的名字代表函数实现的功能,同名的函数一般是实现相同的功能(不然,就不是好的设计,代码)。不同的是,通过重载的方式实现,对不同参数的适配。所以,对于range这样优秀的代码,我们分析一个函数就可以明白,他实现的功能。

总结

上面的invoke说明了三种invoke 函数的情况:

  1. 通过类的指针,类的实例调用带参数的情况
  2. 通过类的指针,类的实例调用类的变量。
  3. 通过函数调用
2025-07-23 09:33:01 2025-07-23 09:33:01.128 -> [main] -> INFO com.fc.V2Application - Starting V2Application v0.0.1-SNAPSHOT using Java 1.8.0_212 on ddad2af35401 with PID 1 (/app.war started by root in /) 2025-07-23 09:33:01 2025-07-23 09:33:01.129 -> [main] -> DEBUG com.fc.V2Application - Running with Spring Boot v2.4.1, Spring v5.3.2 2025-07-23 09:33:01 2025-07-23 09:33:01.129 -> [main] -> INFO com.fc.V2Application - The following profiles are active: dev 2025-07-23 09:33:01 2025-07-23 09:33:01.176 -> [main] -> INFO o.s.b.d.env.DevToolsPropertyDefaultsPostProcessor - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2025-07-23 09:33:02 2025-07-23 09:33:02.134 -> [main] -> INFO o.s.d.r.config.RepositoryConfigurationDelegate - Multiple Spring Data modules found, entering strict repository configuration mode! 2025-07-23 09:33:02 2025-07-23 09:33:02.136 -> [main] -> INFO o.s.d.r.config.RepositoryConfigurationDelegate - Bootstrapping Spring Data Redis repositories in DEFAULT mode. 2025-07-23 09:33:02 2025-07-23 09:33:02.168 -> [main] -> INFO o.s.d.r.config.RepositoryConfigurationDelegate - Finished Spring Data repository scanning in 20 ms. Found 0 Redis repository interfaces. 2025-07-23 09:33:02 2025-07-23 09:33:02.747 -> [main] -> INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'removeDruidAdConfig' of type [com.fc.v2.common.druid.RemoveDruidAdConfig$$EnhancerBySpringCGLIB$$c48737ab] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2025-07-23 09:33:02 2025-07-23 09:33:02.765 -> [main] -> INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'druidStatInterceptor' of type [com.alibaba.druid.support.spring.stat.DruidStatInterceptor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2025-07-23 09:33:02 2025-07-23 09:33:02.767 -> [main] -> INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'druidStatPointcut' of type [org.springframework.aop.support.JdkRegexpMethodPointcut] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2025-07-23 09:33:02 2025-07-23 09:33:02.769 -> [main] -> INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'druidStatAdvisor' of type [org.springframework.aop.support.DefaultPointcutAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2025-07-23 09:33:03 2025-07-23 09:33:03.096 -> [main] -> INFO o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http) 2025-07-23 09:33:03 2025-07-23 09:33:03.110 -> [main] -> INFO org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"] 2025-07-23 09:33:03 2025-07-23 09:33:03.111 -> [main] -> INFO org.apache.catalina.core.StandardService - Starting service [Tomcat] 2025-07-23 09:33:03 2025-07-23 09:33:03.111 -> [main] -> INFO org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.41] 2025-07-23 09:33:04 2025-07-23 09:33:04.184 -> [main] -> INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext 2025-07-23 09:33:04 2025-07-23 09:33:04.185 -> [main] -> INFO o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 3008 ms 2025-07-23 09:33:04 2025-07-23 09:33:04.265 -> [main] -> INFO o.s.boot.web.servlet.RegistrationBean - Filter webStatFilter was not registered (possibly already registered?) 2025-07-23 09:33:04 2025-07-23 09:33:04.298 -> [main] -> DEBUG com.fc.v2.common.conf.PutFilter - Filter 'putFilter' configured for use 2025-07-23 09:33:05 2025-07-23 09:33:05.262 -> [main] -> INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor 2025-07-23 09:33:05 2025-07-23 09:33:05.264 -> [main] -> INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main 2025-07-23 09:33:05 2025-07-23 09:33:05.276 -> [main] -> INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2025-07-23 09:33:05 2025-07-23 09:33:05.276 -> [main] -> INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.2 created. 2025-07-23 09:33:05 2025-07-23 09:33:05.277 -> [main] -> INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized. 2025-07-23 09:33:05 2025-07-23 09:33:05.278 -> [main] -> INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.2) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' 2025-07-23 09:33:05 Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. 2025-07-23 09:33:05 NOT STARTED. 2025-07-23 09:33:05 Currently in standby mode. 2025-07-23 09:33:05 Number of jobs executed: 0 2025-07-23 09:33:05 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads. 2025-07-23 09:33:05 Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered. 2025-07-23 09:33:05 2025-07-23 09:33:05 2025-07-23 09:33:05.278 -> [main] -> INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' 2025-07-23 09:33:05 2025-07-23 09:33:05.278 -> [main] -> INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.2 2025-07-23 09:33:05 2025-07-23 09:33:05.478 -> [main] -> INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} inited 2025-07-23 09:33:05 2025-07-23 09:33:05.723 -> [main] -> DEBUG c.f.v.m.auto.SysQuartzJobMapper.selectByExample - ==> Preparing: select id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status from t_sys_quartz_job 2025-07-23 09:33:05 2025-07-23 09:33:05.941 -> [main] -> DEBUG c.f.v.m.auto.SysQuartzJobMapper.selectByExample - ==> Parameters: 2025-07-23 09:33:06 2025-07-23 09:33:06.005 -> [main] -> WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzSchedulerUtil': Invocation of init method failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: 2025-07-23 09:33:06 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 ### The error may exist in URL [jar:file:/app.war!/WEB-INF/classes!/mybatis/auto/SysQuartzJobMapper.xml] 2025-07-23 09:33:06 ### The error may involve com.fc.v2.mapper.auto.SysQuartzJobMapper.selectByExample-Inline 2025-07-23 09:33:06 ### The error occurred while setting parameters 2025-07-23 09:33:06 ### SQL: select id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status from t_sys_quartz_job 2025-07-23 09:33:06 ### Cause: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 2025-07-23 09:33:06.005 -> [main] -> INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down. 2025-07-23 09:33:06 2025-07-23 09:33:06.005 -> [main] -> INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused. 2025-07-23 09:33:06 2025-07-23 09:33:06.005 -> [main] -> INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete. 2025-07-23 09:33:06 2025-07-23 09:33:06.006 -> [main] -> INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closing ... 2025-07-23 09:33:06 2025-07-23 09:33:06.014 -> [main] -> INFO com.alibaba.druid.pool.DruidDataSource - {dataSource-1} closed 2025-07-23 09:33:06 2025-07-23 09:33:06.016 -> [main] -> INFO org.apache.catalina.core.StandardService - Stopping service [Tomcat] 2025-07-23 09:33:06 2025-07-23 09:33:06.030 -> [main] -> INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener - 2025-07-23 09:33:06 2025-07-23 09:33:06 Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2025-07-23 09:33:06 2025-07-23 09:33:06.047 -> [main] -> ERROR org.springframework.boot.SpringApplication - Application run failed 2025-07-23 09:33:06 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzSchedulerUtil': Invocation of init method failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: 2025-07-23 09:33:06 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 ### The error may exist in URL [jar:file:/app.war!/WEB-INF/classes!/mybatis/auto/SysQuartzJobMapper.xml] 2025-07-23 09:33:06 ### The error may involve com.fc.v2.mapper.auto.SysQuartzJobMapper.selectByExample-Inline 2025-07-23 09:33:06 ### The error occurred while setting parameters 2025-07-23 09:33:06 ### SQL: select id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status from t_sys_quartz_job 2025-07-23 09:33:06 ### Cause: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:429) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1780) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) 2025-07-23 09:33:06 at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) 2025-07-23 09:33:06 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923) 2025-07-23 09:33:06 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) 2025-07-23 09:33:06 at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) 2025-07-23 09:33:06 at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) 2025-07-23 09:33:06 at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) 2025-07-23 09:33:06 at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) 2025-07-23 09:33:06 at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) 2025-07-23 09:33:06 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) 2025-07-23 09:33:06 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) 2025-07-23 09:33:06 at com.fc.V2Application.main(V2Application.java:12) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 2025-07-23 09:33:06 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2025-07-23 09:33:06 at java.lang.reflect.Method.invoke(Method.java:498) 2025-07-23 09:33:06 at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) 2025-07-23 09:33:06 at org.springframework.boot.loader.Launcher.launch(Launcher.java:107) 2025-07-23 09:33:06 at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) 2025-07-23 09:33:06 at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59) 2025-07-23 09:33:06 Caused by: org.springframework.jdbc.BadSqlGrammarException: 2025-07-23 09:33:06 ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 ### The error may exist in URL [jar:file:/app.war!/WEB-INF/classes!/mybatis/auto/SysQuartzJobMapper.xml] 2025-07-23 09:33:06 ### The error may involve com.fc.v2.mapper.auto.SysQuartzJobMapper.selectByExample-Inline 2025-07-23 09:33:06 ### The error occurred while setting parameters 2025-07-23 09:33:06 ### SQL: select id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status from t_sys_quartz_job 2025-07-23 09:33:06 ### Cause: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 ; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:239) 2025-07-23 09:33:06 at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70) 2025-07-23 09:33:06 at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) 2025-07-23 09:33:06 at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446) 2025-07-23 09:33:06 at com.sun.proxy.$Proxy86.selectList(Unknown Source) 2025-07-23 09:33:06 at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230) 2025-07-23 09:33:06 at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139) 2025-07-23 09:33:06 at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76) 2025-07-23 09:33:06 at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) 2025-07-23 09:33:06 at com.sun.proxy.$Proxy114.selectByExample(Unknown Source) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 2025-07-23 09:33:06 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2025-07-23 09:33:06 at java.lang.reflect.Method.invoke(Method.java:498) 2025-07-23 09:33:06 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) 2025-07-23 09:33:06 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) 2025-07-23 09:33:06 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) 2025-07-23 09:33:06 at com.alibaba.druid.support.spring.stat.DruidStatInterceptor.invoke(DruidStatInterceptor.java:73) 2025-07-23 09:33:06 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) 2025-07-23 09:33:06 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) 2025-07-23 09:33:06 at com.sun.proxy.$Proxy115.selectByExample(Unknown Source) 2025-07-23 09:33:06 at com.fc.v2.service.SysQuartzJobService.selectByExample(SysQuartzJobService.java:108) 2025-07-23 09:33:06 at com.fc.v2.service.SysQuartzJobService$$FastClassBySpringCGLIB$$8fc47ef9.invoke(<generated>) 2025-07-23 09:33:06 at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) 2025-07-23 09:33:06 at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687) 2025-07-23 09:33:06 at com.fc.v2.service.SysQuartzJobService$$EnhancerBySpringCGLIB$$b174130e.selectByExample(<generated>) 2025-07-23 09:33:06 at com.fc.v2.common.quartz.QuartzSchedulerUtil.init(QuartzSchedulerUtil.java:42) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 2025-07-23 09:33:06 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2025-07-23 09:33:06 at java.lang.reflect.Method.invoke(Method.java:498) 2025-07-23 09:33:06 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) 2025-07-23 09:33:06 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) 2025-07-23 09:33:06 at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) 2025-07-23 09:33:06 ... 27 common frames omitted 2025-07-23 09:33:06 Caused by: java.sql.SQLSyntaxErrorException: Table 'springbootv2.t_sys_quartz_job' doesn't exist 2025-07-23 09:33:06 at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) 2025-07-23 09:33:06 at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) 2025-07-23 09:33:06 at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) 2025-07-23 09:33:06 at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) 2025-07-23 09:33:06 at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:370) 2025-07-23 09:33:06 at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3461) 2025-07-23 09:33:06 at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:440) 2025-07-23 09:33:06 at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3459) 2025-07-23 09:33:06 at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.execute(PreparedStatementProxyImpl.java:167) 2025-07-23 09:33:06 at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:497) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 2025-07-23 09:33:06 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2025-07-23 09:33:06 at java.lang.reflect.Method.invoke(Method.java:498) 2025-07-23 09:33:06 at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59) 2025-07-23 09:33:06 at com.sun.proxy.$Proxy118.execute(Unknown Source) 2025-07-23 09:33:06 at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:63) 2025-07-23 09:33:06 at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79) 2025-07-23 09:33:06 at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63) 2025-07-23 09:33:06 at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:326) 2025-07-23 09:33:06 at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156) 2025-07-23 09:33:06 at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109) 2025-07-23 09:33:06 at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83) 2025-07-23 09:33:06 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148) 2025-07-23 09:33:06 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2025-07-23 09:33:06 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 2025-07-23 09:33:06 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2025-07-23 09:33:06 at java.lang.reflect.Method.invoke(Method.java:498) 2025-07-23 09:33:06 at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433) 2025-07-23 09:33:06 ... 57 common frames omitted
最新发布
07-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值