mybatis/mybatis-3 · error · ExecutorException
ResultLoader could not load lazily. Environment was not con
Error message
ResultLoader could not load lazily. Environment was not configured.
What it means
ResultLoader.newExecutor builds a throwaway SIMPLE executor to run the nested query behind a lazy property, using the current Configuration's Environment (DataSource + TransactionFactory). If the Configuration has no Environment (typical when it was built programmatically or deserialized without one), lazy loading cannot open a connection and this ExecutorException is thrown.
Source
Thrown at src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java:94
private <E> List<E> selectList() throws SQLException {
Executor localExecutor = executor;
if (Thread.currentThread().getId() != this.creatorThreadId || localExecutor.isClosed()) {
localExecutor = newExecutor();
}
try {
return localExecutor.query(mappedStatement, parameterObject, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER,
cacheKey, boundSql);
} finally {
if (localExecutor != executor) {
localExecutor.close(false);
}
}
}
private Executor newExecutor() {
final Environment environment = configuration.getEnvironment();
if (environment == null) {
throw new ExecutorException("ResultLoader could not load lazily. Environment was not configured.");
}
final DataSource ds = environment.getDataSource();
if (ds == null) {
throw new ExecutorException("ResultLoader could not load lazily. DataSource was not configured.");
}
final TransactionFactory transactionFactory = environment.getTransactionFactory();
final Transaction tx = transactionFactory.newTransaction(ds, null, false);
return configuration.newExecutor(tx, ExecutorType.SIMPLE);
}
public boolean wasNull() {
return resultObject == null;
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Configure the Environment: configuration.setEnvironment(new Environment("id", transactionFactory, dataSource))
- Build the SqlSessionFactory with a SqlSessionFactoryBuilder and a parsed XML that contains <environments default=...>
- In Spring, let mybatis-spring create the factory so the Environment is always set
Example fix
// before
Configuration cfg = new Configuration();
new SqlSessionFactoryBuilder().build(cfg); // no Environment -> lazy load fails
// after
DataSource ds = ...;
Environment env = new Environment("dev", new JdbcTransactionFactory(), ds);
cfg.setEnvironment(env); Defensive patterns
Strategy: validation
Validate before calling
// Verify at startup that lazy loading can work
if (configuration.getEnvironment() == null) {
throw new IllegalStateException("An Environment (DataSource + TransactionFactory) is required for lazy loading");
} Prevention
- Always build the SqlSessionFactory from XML with <environments> or set the Environment programmatically
- In Spring, use SqlSessionFactoryBean so the Environment is configured for you
When it happens
Trigger: Accessing a lazy property when configuration.getEnvironment() returns null — programmatic Configuration without an Environment, a deserialized Configuration that lost it, or a custom SqlSessionFactory setup that skipped environment registration.
Common situations: Using new Configuration() directly and building a SqlSessionFactory without setting an Environment; unit tests with hand-built configurations; Spring setups that replace the environment incorrectly.
Related errors
- ResultLoader could not load lazily. DataSource was not conf
- Cannot lazy load property [" + this.property + "] of deseria
- Cannot get Configuration as configuration factory was not se
- Cannot get Configuration as factory method [" + this.configu
- Cannot get Configuration as factory class [" + this.configur
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/b55d464f33513b63.
Report an issue: GitHub.