Uso de SqlSession

En MyBatis usas un SqlSessionFactory para crear un SqlSession. Una vez tienes una sesión, la usas para ejecutar tus mapped statements, hacer commit o rollback y finalmente cuando no la necesitas la cierras. Con MyBatis-Spring no es necesario que utilices la SqlSessionFactory directamente porque puedes inyectar en tus beans una SqlSession thread safe (reentrante) que hará de forma automática el commit, rollback y se cerrará conforme a la configuración de la transacción en Spring.

SqlSessionTemplate

El SqlSessionTemplate is el corazón de MyBatis-Spring. Implementa SqlSession y está pensado para que sea directamente reemplazable por cualquier código que actualmente use SqlSession. SqlSessionTemplate es thread safe y se puede compartir por más de un DAO.

Cuando se invoca a cualquier método SQL, incluyendo cualquier método de un mapper devuelto por getMapper(), el SqlSessionTemplate se asegurará de que la SqlSession utilizada es la asociada con la transacción Spring en curso. Adicionalmente, se encarga de gestionar su ciclo de vida, incluyendo su cierre, commit o rollback de la sesión si fuera necesario.

Se debe usar siempre un SqlSessionTemplate en lugar de la implementación de sesión por default MyBatis: DefaultSqlSession porque el template puede participar en transacciones Spring y es thread safe con lo que puede ser inyectado en múltiples mappers (proxies). Cambiar de uno a otro puede crear problemas de integridad de datos.

El SqlSessionTemplate puede construirse usando un SqlSessionFactory como argumento de su constructor.

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
@Configuration
public class MyBatisConfig {
  @Bean
  public SqlSessionTemplate sqlSession() throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory());
  }
}

Este bean puede ser inyectado directamente en tus DAOs. Necesitarás una propiedad SqlSession en tu bean como se muestra a continuación:

public class UserDaoImpl implements UserDao {

  private SqlSession sqlSession;

  public void setSqlSession(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
  }

  public User getUser(String userId) {
    return sqlSession.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
  }
}

E inyectar el SqlSessionTemplate de la siguiente forma:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
  <property name="sqlSession" ref="sqlSession" />
</bean>

El SqlSessionTemplate tiene también un constructor que recibe como parámetro un ExecutorType. Esto permite construir, por ejemplo, una SqlSession batch utilizando la siguiente configuracíon de Spring:

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0" ref="sqlSessionFactory" />
  <constructor-arg index="1" value="BATCH" />
</bean>
@Configuration
public class MyBatisConfig {
  @Bean
  public SqlSessionTemplate sqlSession() throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory(), ExecutorType.BATCH);
  }
}

Ahora todos tus statements se ejecutarán en batch de forma que puedes programar lo siguiente:

public class UserService {
  private final SqlSession sqlSession;
  public UserService(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
  }
  public void insertUsers(List<User> users) {
    for (User user : users) {
      sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user);
    }
  }
}

Fijate que esta configuración si el método de ejecución deseado es distinto del establecido por defecto en el SqlSessionFactory.

La contrapartida de esto es que no es posible cambiar el méodo de ejecución dentro de una transacción. Por tanto asegurate que o bien todas las llamadas a un SqlSessionTemplates con distinto método de ejecución se ejecutan en una transacción diferente (p.ej: with PROPAGATION_REQUIRES_NEW) o completamente fuera de la transacción.

SqlSessionDaoSupport

SqlSessionDaoSupport es una clase de soporte abstracta que proporciona un SqlSession. Llamando a getSqlSession() obtiene un SqlSessionTemplate que puedes utilizar para ejecutar métodos SQL, como sigue:

public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
  public User getUser(String userId) {
    return getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
  }
}

Normalmente es preferible usar un MapperFactoryBean a esta clase dao que no requeire código extra. Pero esta clase es de utilidad cuando es necesario hacer algún otro tipo de trabajo no-MyBatis en el DAO y se necesitan clases concretas.

SqlSessionDaoSupport que se informe la propiedad sqlSessionFactory o la sqlSessionTemplate. Si se informan ambas propiedades, la sqlSessionFactory se ignora.

Asumiendo una clase UserDaoImpl que extiende SqlSessionDaoSupport, se puede configurar Spring de la siguiente forma:

<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl">
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>