pagehelper-org/Mybatis-PageHelper · error · RuntimeException

Class must provide a constructor without parameters

Error message

${autoDialectClassStr}Class must provide a constructor without parameters

What it means

After resolving the autoDialectClass, PageAutoDialect instantiates it via ClassUtil.newInstance; any exception other than ClassNotFoundException (missing public no-arg constructor, instantiation failure, constructor throwing) is wrapped in a RuntimeException '<class>Class must provide a constructor without parameters'.

Solutions

  1. Add a public no-argument constructor to the AutoDialect implementation (properties are applied later via setProperties).
  2. Make the class concrete, public, and static if nested.
  3. Check the cause of this RuntimeException for the true reflective error.
  4. Initialize external dependencies lazily in setLocalPageSize/setProperties rather than in the constructor.

Example fix

// before
public class MyAutoDialect implements AutoDialect {
    public MyAutoDialect(Properties p) { ... } // no no-arg ctor
}
// after
public class MyAutoDialect implements AutoDialect {
    public MyAutoDialect() { }
    @Override
    public AbstractHelperDialect extractDialect(...) { ... }
}
Defensive patterns

Strategy: try-catch

Validate before calling

Class<?> c = Class.forName(autoDialectClass);
if (c.isInterface() || java.lang.reflect.Modifier.isAbstract(c.getModifiers())
        || java.lang.reflect.Constructor.class == null && c.getConstructors().length == 0) {
    throw new IllegalStateException(autoDialectClass + " needs a public no-arg constructor");
}
c.getDeclaredConstructor().newInstance();

Type guard

static boolean hasNoArgCtor(Class<?> c) {
    try { c.getDeclaredConstructor(); return java.lang.reflect.Modifier.isPublic(c.getModifiers()); }
    catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
    autoDialectDelegate = ClassUtil.newInstance(autoDialectClass, properties);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().endsWith("must provide a constructor without parameters")) {
        throw new IllegalStateException("Add a public no-arg constructor to " + autoDialectClass, e.getCause());
    }
    throw e;
}

Prevention

When it happens

Trigger: The configured AutoDialect class exists but has no accessible no-argument constructor, is abstract/an interface, or its constructor (or static init) throws when invoked during setProperties.

Common situations: Custom AutoDialect written with a constructor taking Properties only; class made abstract; constructor depending on a service that is unavailable at plugin init; nested class not declared static (no implicit no-arg constructor).

Related errors


AI-assisted analysis of pagehelper-org/Mybatis-PageHelper@c692616c5b (2026-09-08). Data as JSON: /api/errors/2f9a46a0b5184262. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/com/github/pagehelper/page/PageAutoDialect.java:288

     *
     * @param properties
     */
    private void initAutoDialectClass(Properties properties) {
        String autoDialectClassStr = properties.getProperty("autoDialectClass");
        if (StringUtil.isNotEmpty(autoDialectClassStr)) {
            try {
                Class<? extends AutoDialect> autoDialectClass;
                if (autoDialectMap.containsKey(autoDialectClassStr)) {
                    autoDialectClass = autoDialectMap.get(autoDialectClassStr);
                } else {
                    autoDialectClass = (Class<AutoDialect>) Class.forName(autoDialectClassStr);
                }
                this.autoDialectDelegate = ClassUtil.newInstance(autoDialectClass, properties);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("Make sure that the AutoDialect implementation class ("
                        + autoDialectClassStr + ") for the autoDialectClass configuration exists!", e);
            } catch (Exception e) {
                throw new RuntimeException(autoDialectClassStr + "Class must provide a constructor without parameters", e);
            }
        } else {
            this.autoDialectDelegate = new DataSourceNegotiationAutoDialect();
        }
    }

    /**
     * 初始化方言别名
     *
     * @param properties
     */
    private void initDialectAlias(Properties properties) {
        String dialectAlias = properties.getProperty("dialectAlias");
        if (StringUtil.isNotEmpty(dialectAlias)) {
            String[] alias = dialectAlias.split(";");
            for (int i = 0; i < alias.length; i++) {
                String[] kv = alias[i].split("=");
                if (kv.length != 2) {

View on GitHub (pinned to c692616c5b)