1. Introducción
MyBatis es un marco de persistencia de código abierto que simplifica la implementación del acceso a la base de datos en aplicaciones Java. Proporciona soporte para SQL personalizado, procedimientos almacenados y diferentes tipos de relaciones de mapeo.
En pocas palabras, es una alternativa a JDBC e Hibernate.
2. Dependencias de Maven
Para hacer uso de MyBatis, necesitamos agregar la dependencia a nuestro pom.xml:
org.mybatis mybatis 3.4.4
La última versión de la dependencia se puede encontrar aquí.
3. API de Java
3.1. SQLSessionFactory
SQLSessionFactory es la clase principal de todas las aplicaciones MyBatis. Esta clase se instancia utilizando SqlSessionFactoryBuilder' s constructor () método que carga un archivo XML de configuración:
String resource = "mybatis-config.xml"; InputStream inputStream Resources.getResourceAsStream(resource); SQLSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
El archivo de configuración de Java incluye configuraciones como la definición de la fuente de datos, los detalles del administrador de transacciones y una lista de mapeadores que definen las relaciones entre las entidades, estos juntos se utilizan para construir la instancia de SQLSessionFactory :
public static SqlSessionFactory buildqlSessionFactory() { DataSource dataSource = new PooledDataSource(DRIVER, URL, USERNAME, PASSWORD); Environment environment = new Environment("Development", new JdbcTransactionFactory(), dataSource); Configuration configuration = new Configuration(environment); configuration.addMapper(PersonMapper.class); // ... SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); return builder.build(configuration); }
3.2. SQLSession
SQLSession contiene métodos para realizar operaciones de base de datos, obtener mapeadores y administrar transacciones. Se puede crear una instancia desde la clase SQLSessionFactory . Las instancias de esta clase no son seguras para subprocesos.
Después de realizar la operación de la base de datos, la sesión debe cerrarse. Dado que SqlSession implementa la interfaz AutoCloseable , podemos usar el bloque try-with-resources :
try(SqlSession session = sqlSessionFactory.openSession()) { // do work }
4. Mapeadores
Los mapeadores son interfaces Java que mapean métodos a las correspondientes sentencias SQL. MyBatis proporciona anotaciones para definir las operaciones de la base de datos:
public interface PersonMapper { @Insert("Insert into person(name) values (#{name})") public Integer save(Person person); // ... @Select( "Select personId, name from Person where personId=#{personId}") @Results(value = { @Result(property = "personId", column = "personId"), @Result(property="name", column = "name"), @Result(property = "addresses", javaType = List.class, column = "personId", [email protected](select = "getAddresses")) }) public Person getPersonById(Integer personId); // ... }
5. Anotaciones MyBatis
Veamos algunas de las principales anotaciones proporcionadas por MyBatis:
- @Insert, @Select, @Update, @Delete : esas anotaciones representan declaraciones SQL que se ejecutarán llamando a métodos anotados:
@Insert("Insert into person(name) values (#{name})") public Integer save(Person person); @Update("Update Person set name= #{name} where personId=#{personId}") public void updatePerson(Person person); @Delete("Delete from Person where personId=#{personId}") public void deletePersonById(Integer personId); @Select("SELECT person.personId, person.name FROM person WHERE person.personId = #{personId}") Person getPerson(Integer personId);
- @Results : es una lista de asignaciones de resultados que contiene los detalles de cómo se asignan las columnas de la base de datos a los atributos de la clase Java:
@Select("Select personId, name from Person where personId=#{personId}") @Results(value = { @Result(property = "personId", column = "personId") // ... }) public Person getPersonById(Integer personId);
- @Result : representa una única instancia de Result fuera de la lista de resultados recuperados de @Results. Incluye detalles como el mapeo de la columna de la base de datos a la propiedad del bean Java, el tipo Java de la propiedad y también la asociación con otros objetos Java:
@Results(value = { @Result(property = "personId", column = "personId"), @Result(property="name", column = "name"), @Result(property = "addresses", javaType =List.class) // ... }) public Person getPersonById(Integer personId);
- @Many : especifica una asignación de un objeto a una colección de los otros objetos:
@Results(value ={ @Result(property = "addresses", javaType = List.class, column = "personId", [email protected](select = "getAddresses")) })
Aquí getAddresses es el método que devuelve la colección de direcciones consultando la tabla de direcciones.
@Select("select addressId, streetAddress, personId from address where personId=#{personId}") public Address getAddresses(Integer personId);
Similar a la anotación @Many , tenemos la anotación @One que especifica la relación de mapeo uno a uno entre objetos.
- @MapKey : se utiliza para convertir la lista de registros en un mapa de registros con la clave definida por elatributo de valor :
@Select("select * from Person") @MapKey("personId") Map getAllPerson();
- @Options : esta anotación especifica una amplia gama de conmutadores y configuraciones que se definirán para que, en lugar de definirlos en otras declaraciones, podamos @Options para definirlos:
@Insert("Insert into address (streetAddress, personId) values(#{streetAddress}, #{personId})") @Options(useGeneratedKeys = false, flushCache=true) public Integer saveAddress(Address address);
6. SQL dinámico
El SQL dinámico es una característica muy poderosa proporcionada por MyBatis. Con esto, podemos estructurar nuestro SQL complejo con precisión.
Con el código JDBC tradicional, tenemos que escribir sentencias SQL, concatenarlas con la precisión de los espacios entre ellas y poner las comas en los lugares correctos. Esto es muy propenso a errores y muy difícil de depurar, en el caso de declaraciones SQL grandes.
Exploremos cómo podemos usar SQL dinámico en nuestra aplicación:
@SelectProvider(type=MyBatisUtil.class, method="getPersonByName") public Person getPersonByName(String name);
Aquí hemos especificado una clase y un nombre de método que realmente construye y genera el SQL final:
public class MyBatisUtil { // ... public String getPersonByName(String name){ return new SQL() {{ SELECT("*"); FROM("person"); WHERE("name like #{name} || '%'"); }}.toString(); } }
SQL dinámico proporciona todas las construcciones de SQL como una clase, por ejemplo , SELECT , WHERE , etc. Con esto, podemos cambiar dinámicamente la generación de la cláusula WHERE .
7. Soporte para procedimientos almacenados
También podemos ejecutar el procedimiento almacenado usando la anotación @Select . Aquí necesitamos pasar el nombre del procedimiento almacenado, la lista de parámetros y usar una llamada explícita a ese procedimiento:
@Select(value= "{CALL getPersonByProc(#{personId, mode=IN, jdbcType=INTEGER})}") @Options(statementType = StatementType.CALLABLE) public Person getPersonByProc(Integer personId);
8. Conclusión
En este tutorial rápido, hemos visto las diferentes funciones proporcionadas por MyBatis y cómo facilita el desarrollo de aplicaciones para bases de datos. También hemos visto varias anotaciones proporcionadas por la biblioteca.
El código completo de este artículo está disponible en GitHub.