5. Mybatis
●
Es un framework de persistencia disponible para Java y .NET.
●
No se trata de un ORM.
●
Mapea sentencias SQL con objetos Java a través de interfaces
definidas en XML o con anotaciones.
●
Se integra con Spring y Maven.
●
Cache declarativa.
●
Previene el témido SQL Inyection y no nos tenemos que
preocupar de las conexiones.
6. Mybatis vs Hibernate vs JDBC
●
●
●
●
●
Ahorramos un 95% de código con respecto a JDBC ya que el
mapeo de objetos se puede inferir.
Hibernate tiene una fuerte curva de aprendizaje y su
funcionamiento no es natural.
Con Hibernate perdemos el control de las sentencias que
realmente se están ejecutando, hace magia.
Hibernate generalmente no se utiliza adecuádamente y no se
adapta bien a base de datos impuestas.
Mybatis ahorra mucho código, no es complejo, mantiene un
control total y trae cache por defecto.
8. Código de ejemplo
String resource = "SQLMapConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlMapper = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
} finally {
session.close();
}
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" parameterType="int" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
9. Utilizándolo con Maven y Spring
●
Añadir al menos estas dependencias a nuestro proyecto.
<dependency>
<groupid>org.mybatis</groupid>
<artifactid>mybatis</artifactid>
<version>3.2.3</version>
</dependency>
<dependency>
<groupid>org.mybatis</groupid>
<artifactid>mybatis-spring</artifactid>
<version>1.2.1</version>
</dependency>
10. Utilizándolo con Maven y Spring
●
Añadimos un datasource a nuestro applicationContext.
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql:tutoriales" />
<property name="username" value="postgres" />
<property name="password" value="autentia" />
</bean>
●
Añadimos también un transaction manager.
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
11. Utilizándolo con Maven y Spring
●
Creamos un SQLSessionFactory donde indicamos la
localización de los mappers.xml y el datasource.
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="mapperLocations"
value="classpath*:mappers/*.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
12. Utilizándolo con Maven y Spring
●
El siguiente bean nos ahorra tener que crear un bean por cada
mapper que queramos declarar.
<bean class="org.mybatis.spring.annotation.MapperScannerPostProcessor">
<property name="basePackage" value="com.autentia.dao" />
</bean>
●
En caso contrario, esta declaración por cada mapper:
<bean id="tutorialMapper"
class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface"
value="com.autentia.dao.TutorialMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
13. Utilizándolo con Maven y Spring
●
Creamos la interfaz con los métodos necesarios.
package com.autentia.dao;
import org.springframework.stereotype.Repository;
import com.autentia.model.Tutorial;
public interface TutorialesMapper {
public Tutorial getById(Integer idTutorial);
public List<Tutorial> getByCategoriaValoracion(@Param(“categoria”)
String categoria, @Param(“valoracion) Integer valoracion);
}
14. Utilizándolo con Maven y Spring
●
Creamos el mapper que implementa la interfaz.
<mapper namespace="com.autentia.dao.TutorialesMapper">
<resultMap type="com.autentia.model.Tutorial" id="tutorialResult">
<id column="id_tutorial" property="idTutorial" javaType="int"/>
<result column="titulo" property="titulo" javaType="string"/>
<result column="categoria" property="categoria" javaType="string"/>
<result column="valoracion" property="valoracion" javaType="int"/>
</resultMap>
<select id="getById" parameterType="int" resultMap="tutorialResult">
<!--[resultType="com.autentia.model.Tutorial"] (modelo == tabla) -->
select id_tutorial, titulo, categoria, valoracion from
tutoriales where id_tutorial = #{id_tutorial}
</select>
</mapper>
15. Utilizándolo con Maven y Spring
Creamos un test para probarlo.
●
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/applicationContext.xml"})
public class TutorialesMapperTest {
@Resource
private TutorialesMapper tutorialesMapper;
}
@Test
public void shouldGetTutorialById() {
Long idTutorial = 1L;
Tutorial tutorial = tutorialesMapper.getById(idTutorial);
assertNotNull(tutorial);
}
19. Técnicas básicas en los mappers
●
Paso de N parámetros
public List<Tutorial> getByCategoriaValoracion(@Param(“categoria”)
String categoria, @Param(“valoracion) Integer valoracion);
public List<Tutorial> getByCategoriaValoracion(Map datos);
<select id="getByCategoriaValoracion"
parameterType="map" resultMap="tutorialResult">
<!-- La sentencia que sea-->
</select>
20. Técnicas básicas en los mappers
●
Reutilización de código SQL.
<sql id="selectTutoriales">
select id_tutorial, titulo, categoria, valoracion
from tutoriales
</sql>
<select id="getById" parameterType="int" resultMap="tutorialResult">
<include refid="selectTutoriales"/>
where id_tutorial = #{id_tutorial}
</select>
21. Técnicas básicas en los mappers
●
Añadimos cache
<cache/>
●
●
Esta declaración por defecto cachea todas las sentencias
SELECT y hace que se vacíe para las sentencias INSERT,
DELETE y UPDATE.
También se puede asociar con otros gestores de cache como
osCache, ehCache o con uno propio.
22. Técnicas básicas en los mappers
●
Sustitución de cadenas
SELECT * FROM tutoriales ORDER BY ${column}
●
●
En ocasiones nos interesa pasar una parámetro como cadena y
que Mybatis no lo convierta en un ? del PreparedStatement.
¡Cuidado! Aquí si que podemos estar incurriendo en el témido
SQL inyection.
23. Técnicas básicas en los mappers
●
Llamadas a procedimientos almacenados
●
Para el caso de Oracle
<select id="callGetTotalCityStateId" parameterType="pojo"
statementType="CALLABLE">
statementType="CALLABLE"
{ CALL getTotalCityStateId(
#{stateId, mode=IN, jdbcType=INTEGER},
#{total, mode=OUT, jdbcType=INTEGER})}
</select>
●
Para el caso de PostgreSQL
<select id="sumar" parameterType="map" resultType="int">
SELECT * FROM sumar(#{a},#{b});
</select>