DefaultSqlSession.java
- /*
- * Copyright 2009-2024 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.ibatis.session.defaults;
- import java.io.IOException;
- import java.sql.Connection;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.apache.ibatis.binding.BindingException;
- import org.apache.ibatis.cursor.Cursor;
- import org.apache.ibatis.exceptions.ExceptionFactory;
- import org.apache.ibatis.exceptions.TooManyResultsException;
- import org.apache.ibatis.executor.BatchResult;
- import org.apache.ibatis.executor.ErrorContext;
- import org.apache.ibatis.executor.Executor;
- import org.apache.ibatis.executor.result.DefaultMapResultHandler;
- import org.apache.ibatis.executor.result.DefaultResultContext;
- import org.apache.ibatis.mapping.MappedStatement;
- import org.apache.ibatis.reflection.ParamNameResolver;
- import org.apache.ibatis.session.Configuration;
- import org.apache.ibatis.session.ResultHandler;
- import org.apache.ibatis.session.RowBounds;
- import org.apache.ibatis.session.SqlSession;
- /**
- * The default implementation for {@link SqlSession}. Note that this class is not Thread-Safe.
- *
- * @author Clinton Begin
- */
- public class DefaultSqlSession implements SqlSession {
- private final Configuration configuration;
- private final Executor executor;
- private final boolean autoCommit;
- private boolean dirty;
- private List<Cursor<?>> cursorList;
- public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
- this.configuration = configuration;
- this.executor = executor;
- this.dirty = false;
- this.autoCommit = autoCommit;
- }
- public DefaultSqlSession(Configuration configuration, Executor executor) {
- this(configuration, executor, false);
- }
- @Override
- public <T> T selectOne(String statement) {
- return this.selectOne(statement, null);
- }
- @Override
- public <T> T selectOne(String statement, Object parameter) {
- // Popular vote was to return null on 0 results and throw exception on too many.
- List<T> list = this.selectList(statement, parameter);
- if (list.size() == 1) {
- return list.get(0);
- }
- if (list.size() > 1) {
- throw new TooManyResultsException(
- "Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
- } else {
- return null;
- }
- }
- @Override
- public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
- return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
- }
- @Override
- public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
- return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
- }
- @Override
- public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
- final List<? extends V> list = selectList(statement, parameter, rowBounds);
- final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
- configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
- final DefaultResultContext<V> context = new DefaultResultContext<>();
- for (V o : list) {
- context.nextResultObject(o);
- mapResultHandler.handleResult(context);
- }
- return mapResultHandler.getMappedResults();
- }
- @Override
- public <T> Cursor<T> selectCursor(String statement) {
- return selectCursor(statement, null);
- }
- @Override
- public <T> Cursor<T> selectCursor(String statement, Object parameter) {
- return selectCursor(statement, parameter, RowBounds.DEFAULT);
- }
- @Override
- public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
- try {
- MappedStatement ms = configuration.getMappedStatement(statement);
- dirty |= ms.isDirtySelect();
- Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
- registerCursor(cursor);
- return cursor;
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- @Override
- public <E> List<E> selectList(String statement) {
- return this.selectList(statement, null);
- }
- @Override
- public <E> List<E> selectList(String statement, Object parameter) {
- return this.selectList(statement, parameter, RowBounds.DEFAULT);
- }
- @Override
- public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
- return selectList(statement, parameter, rowBounds, Executor.NO_RESULT_HANDLER);
- }
- private <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
- try {
- MappedStatement ms = configuration.getMappedStatement(statement);
- dirty |= ms.isDirtySelect();
- return executor.query(ms, wrapCollection(parameter), rowBounds, handler);
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- @Override
- public void select(String statement, Object parameter, ResultHandler handler) {
- select(statement, parameter, RowBounds.DEFAULT, handler);
- }
- @Override
- public void select(String statement, ResultHandler handler) {
- select(statement, null, RowBounds.DEFAULT, handler);
- }
- @Override
- public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
- selectList(statement, parameter, rowBounds, handler);
- }
- @Override
- public int insert(String statement) {
- return insert(statement, null);
- }
- @Override
- public int insert(String statement, Object parameter) {
- return update(statement, parameter);
- }
- @Override
- public int update(String statement) {
- return update(statement, null);
- }
- @Override
- public int update(String statement, Object parameter) {
- try {
- dirty = true;
- MappedStatement ms = configuration.getMappedStatement(statement);
- return executor.update(ms, wrapCollection(parameter));
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- @Override
- public int delete(String statement) {
- return update(statement, null);
- }
- @Override
- public int delete(String statement, Object parameter) {
- return update(statement, parameter);
- }
- @Override
- public void commit() {
- commit(false);
- }
- @Override
- public void commit(boolean force) {
- try {
- executor.commit(isCommitOrRollbackRequired(force));
- dirty = false;
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- @Override
- public void rollback() {
- rollback(false);
- }
- @Override
- public void rollback(boolean force) {
- try {
- executor.rollback(isCommitOrRollbackRequired(force));
- dirty = false;
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error rolling back transaction. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- @Override
- public List<BatchResult> flushStatements() {
- try {
- return executor.flushStatements();
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error flushing statements. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
- @Override
- public void close() {
- try {
- executor.close(isCommitOrRollbackRequired(false));
- closeCursors();
- dirty = false;
- } finally {
- ErrorContext.instance().reset();
- }
- }
- private void closeCursors() {
- if (cursorList != null && !cursorList.isEmpty()) {
- for (Cursor<?> cursor : cursorList) {
- try {
- cursor.close();
- } catch (IOException e) {
- throw ExceptionFactory.wrapException("Error closing cursor. Cause: " + e, e);
- }
- }
- cursorList.clear();
- }
- }
- @Override
- public Configuration getConfiguration() {
- return configuration;
- }
- @Override
- public <T> T getMapper(Class<T> type) {
- return configuration.getMapper(type, this);
- }
- @Override
- public Connection getConnection() {
- try {
- return executor.getTransaction().getConnection();
- } catch (SQLException e) {
- throw ExceptionFactory.wrapException("Error getting a new connection. Cause: " + e, e);
- }
- }
- @Override
- public void clearCache() {
- executor.clearLocalCache();
- }
- private <T> void registerCursor(Cursor<T> cursor) {
- if (cursorList == null) {
- cursorList = new ArrayList<>();
- }
- cursorList.add(cursor);
- }
- private boolean isCommitOrRollbackRequired(boolean force) {
- return !autoCommit && dirty || force;
- }
- private Object wrapCollection(final Object object) {
- return ParamNameResolver.wrapToMapIfCollection(object, null);
- }
- /**
- * @deprecated Since 3.5.5
- */
- @Deprecated
- public static class StrictMap<V> extends HashMap<String, V> {
- private static final long serialVersionUID = -5741767162221585340L;
- @Override
- public V get(Object key) {
- if (!super.containsKey(key)) {
- throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + this.keySet());
- }
- return super.get(key);
- }
- }
- }