En Java, existen múltiples soluciones para gestionar la interacción con la base de datos. Algunas nos acercan más y otras nos alejan del uso de SQL nativos. O, incluso, nos proporcionan un lenguaje basado en SQL pero distinto del lenguaje nativo de la base de datos que estemos usando: mySQL, Oracle, SQL Server, PosgreSQL, MariaDB, etc.
Cuando iniciamos un nuevo proyecto, suele ser una de las dudas que nos entran. Normalmente, elegimos sobre el que tenemos más experiencia, pero también nos podemos decantar por otro que se ajuste mejor a las necesidades del proyecto o a la experiencia del resto del equipo.
Vamos a repasar las diferencias entre los tres ORM (Object Relacional Mapping) más comunes en Java, para que nos ayude a decidir o, al menos, a ser conscientes de los puntos fuertes y débiles que cada uno nos puede aportar.
Tabla de Contenidos
Diferencias entre JPA, Hibernate y MyBatis
Partimos de que los tres frameworks nos ayudan a gestionar las interacciones con la base de datos: consultar, añadir, modificar y eliminar registros. Simplifican el acceso a los datos y nos ahorran picar mucho código repetitivo.
JPA
Sobre qué es JPA (Java Persistence API), podemos decir que es una especificación para acceder y gestionar bases de datos en Java. Proporciona un conjunto estándar de API para acceder a bases de datos, lo que facilita el desarrollo de aplicaciones que puedan funcionar con distintos sistemas de gestión de bases de datos (SGBD). Es decir, se puede usar indistintamente con cualquier motor de base de datos: Oracle, SQL Server, MySQL, ets. Hibernate y EclipseLink, entre otros, implementan JPA.
La primera versión, la 1.0 fue lanzada en 2006 como parte de la especificación de EJB 3.0.
- JPA 2.0 – Fue lanzada a finales de 2009, con las siguiente mejoras:
- Soporta validación.
- Expande la funcionalidad del mapero relacional.
- Comparte el objeto de soporte de caché.
- JPA 2.1 – Fue lanzada en 2013 con estas novedades:
- Permite el fetching de objetos.
- Soporta Criteria para update/delete.
- Puede generar el schema.
- JPA 2.2 – Salió a la luz en 2017. Algunas mejoras son:
- Soporte para los objetos Data y Time de Java 8.
- Permite la anotación @Repeatable para cuando se quiere aplicar las mismas anotaciones a una declaración o tipo.
- Permita utilizar anotaciones JPA en meta-anotaciones.
- Ofrece la habilitad de crear un stream a partir del resultado de una consulta o query.
Hibernate
Por otro lado, ¿qué es Hibernate? Pues Hibernate es una implementación de código abierto de JPA que proporciona características adicionales para trabajar con bases de datos. Además de proporcionar las API estándar de JPA, Hibernate ofrece almacenamiento en caché, carga diferida y otras funciones que facilitan el trabajo con bases de datos en un entorno de alto rendimiento. Hibernate es muy utilizado y está respaldado por buen soporte, por lo que es una opción popular para los desarrolladores que quieren una implementación extendida de JPA.
Hibernate utiliza su propia lenguaje SQL, llamado HQL (Hibernate Query Language), el cual es independiente del motor de base de datos utilizado. Además, es capaz de gestionar el pool de conexiones y la concurrencia de las mismas. Y puede mejorar el rendimiento si se utiliza correctamente el lazy loading que proporciona.
Por otro lado, puede dificultar la depuración de las queries que lanza, al utilizar HQL, ya que la traducción que hace a SQL a veces no es fácil de entender en queries complejas. Además, en proyectos pequeños puede ser contraproducente
MyBatis
Por último, MyBatis ofrece una forma más flexible de acceder a bases de datos en Java. A diferencia de JPA, que utiliza anotaciones para asignar objetos Java a tablas de bases de datos, MyBatis utiliza anotaciones, pero también admite XML para realizar la misma tarea.
Esto proporciona un mayor control sobre el proceso de mapeo y facilita el manejo de escenarios de acceso a bases de datos más complejos. MyBatis también es una buena opción para los desarrolladores que prefieren trabajar con XML o anotaciones en lugar de anotaciones JPA.
Además, también facilita la ejecución de funciones y procedimientos de base de datos, pudiendo aprovechar la simplicidad que ofrece MyBatis para ello.

Un ejemplo con JPA
Vamos a ver ejemplos de cómo sería el uso de cada framework para un entidad Usuario, para poder compararlos un poco más en la práctica. Empecemos por JPA.
Lo primero sería crear una clase de tipo Entidad (con la anotación @Entity), llamada usuario. Sus campos se corresponderán con los campos de la tabla en base de datos aunque, mediante anotaciones, se pueden llamar de distinta manera. Estos serán privados, pero se accederá a ellos con los getters y setters públicos, como en cualquier Bean.
Con otras anotaciones, como @Id, se puede definir el campo que será el id o clave primaria de la tabla.
@Entity
public class Usuario {
@Id
private Long id;
private String nombre;
private String email;
// getters and setters...
}Además, se debe crear un DAO (Data Access Object) con un EntityManager que será el encargado de realizar las operaciones CRUD sobre la tabla.
public class UsuarioDAO {
@PersistenceContext
private EntityManager em;
public Usuario findById(Long id) {
return em.find(User.class, id);
}
public void save(Usuario usuario) {
em.persist(usuario);
}
public void update(Usuario usuario) {
em.merge(usuario);
}
public void delete(Usuario usuario) {
em.remove(usuario);
}
}Un ejemplo con Hibernate
Con Hibernate, también se necesita una clase «Usuario», que será la entidad, cuyos campos se corresponderán con los de la tabla de base de datos. Con anotaciones, se puede enlazar cada campo de base de datos con su correspondencia en la entidad si tienen distinto nombre. Esto también se podría hacer mediante un XML (ficheros *.hbm.xml), aunque suele ser más cómo hacerlo en la propia entidad. Pero que sepas que existe esa posibilidad.
Además, dispones de otras anotaciones como la autogeneración del ID que se ve en este ejemplo, sobre el campo id.
@Entity
public class Usuario{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
private String email;
// getters and setters...
}También deberás crear un DAO para las operaciones CRUD sobre la tabla Usuario. En este caso, irán sobre el sessionFactory, que es el que se encarga de gestionar las sesiones de bases de datos en Hibernate, haciendo más eficiente la gestión de las mismas, aunque a veces requiera de ajustes en la configuración.
public class UsuarioDAO {
private SessionFactory sessionFactory;
public UsuariofindById(Long id) {
Session session = sessionFactory.getCurrentSession();
return session.get(Usuario.class, id);
}
public void save(Usuario usuario) {
Session session = sessionFactory.getCurrentSession();
session.save(usuario);
}
public void update(Usuario usuario) {
Session session = sessionFactory.getCurrentSession();
session.update(usuario);
}
public void delete(Usuario usuario) {
Session session = sessionFactory.getCurrentSession();
session.delete(usuario);
}
}Un ejemplo con MyBatis
Con MyBatis, deberías crear una clase Java class llamada «Usuario» cuyos campos coincidan con las columnas de la tabla y, ademas, crear un mapeo en un fichero XML, o bien, utilizar las anotaciones de MyBatis para mapear los campos de la tabla. Deberías utilizar la SQLSession para llevar a cabo las operaciones CRUD sobre la tabla Usuario. Por ejemplo,
public class Usuario {
private Long id;
private String name;
private String email;
// getters and setters...
}Necesitamos un mapeador para las sentencias SQL y los objetos Java. Las sentencias SQL se puede parametrizar, lo que hace muy cómodo de leer sobre el código.
public interface UsuarioMapper {
@Select("SELECT * FROM usuarios WHERE id = #{id}")
Usuario findById(@Param("id") Long id);
@Insert("INSERT INTO usuarios(name, email, age) VALUES
(#{name}, #{email}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void save(Usuario usuario);
@Update("UPDATE usuarios SET name = #{name}, email = #{email},
age = #{age} WHERE id = #{id}")
void update(Usuario usuario);
@Delete("DELETE FROM users WHERE id = #{id}")
void delete(Usuario usuario);
}En el DAO, como siempre, irán las operaciones sobre base de datos. Esta vez, basadas en el objeto SqlSession.
public class UsuarioDAO {
private SqlSession sqlSession;
public User findById(Long id) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.findById(id);
}
public void save(Usuario usuario) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.save(usuario);
}
public void update(Usuario usuario) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.update(user);
}
public void delete(Usuario usuario) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);¿Qué framework elegir?
La respuesta a esta pregunta depende de sus necesidades y preferencias específicas, como siempre.
Si quieres una forma estándar de acceder a bases de datos en Java, JPA es una buena opción. Además, proporciona un alto nivel de abstracción, produciendo un código fácil de leer y mantener.
Si deseas una implementación de JPA con más funciones, Hibernate es la mejor opción. Hibernate es un ORM muy maduro con funcionalidades de caché muy útiles para mejorar el rendimiento de tus aplicaciones.
Y si quieres una forma más flexible de acceder a bases de datos y no te importa escribir XML o anotaciones para mapear tus objetos, MyBatis es tu elección. MyBatis es un framework más ligero y flexible lo cual te da más control sobre las consultas SQL.
En cualquier caso, las 3 son buenas opciones y vas a encontrar bastante soporte detrás de ellas. Así que también hay que valorar otras cosas como la experiencia de los miembros del equipo de desarrollo.
Y tú, ¿cuál sueles utilizar? ¿Cuál es tu preferido?





