ORM for Java: comparison and examples
In modern Java development, ORM (Object-Relational Mapping) is a standard approach for interacting with relational databases. ORM allows you to work with tables as objects, reducing the amount of boilerplate code. On PythonLib, we will cover four main tools: Hibernate, MyBatis, JPA, and Spring Data JPA. You will learn their features, strengths, and get ready-made examples.
What is ORM and why is it needed?
ORM is a layer between a Java application and a database. It automates:
- Mapping Java classes to tables
- Generating SQL queries
- Transaction management
- Data caching
Without ORM, a developer has to write JDBC code manually, which increases development time and the risk of errors.
1. Hibernate — powerful and mature
Hibernate is the most popular ORM framework for Java. It fully implements JPA (Java Persistence API) and adds its own capabilities: second-level caching, lazy loading, HQL (Hibernate Query Language). Hibernate automatically generates SQL and manages the state of objects.
Example: entity and simple query
import javax.persistence.*;
@Entity@Table(name = "users")public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Column(nullable = false) private String name;
@Column(unique = true) private String email;
// getters and setters}
// UsageSession session = sessionFactory.openSession();User user = session.get(User.class, 1L);System.out.println(user.getName());session.close();Pros: automatic schema generation, powerful HQL, support for cascade operations, large community.
Cons: complexity of configuration, performance issues with N+1 queries, "magical" behavior.
2. MyBatis — SQL under control
MyBatis is not a full-fledged ORM, but rather an SQL Mapper. You write SQL manually, and MyBatis maps the results to Java objects. This gives you full control over queries and optimization.
Example: mapper and XML configuration
// Mapper interfacepublic interface UserMapper { User selectUser(@Param("id") long id);}
// XML mapper (UserMapper.xml)<mapper namespace="com.example.UserMapper"> <select id="selectUser" resultType="User"> SELECT * FROM users WHERE id = #{id} </select></mapper>
// UsageSqlSession session = sqlSessionFactory.openSession();UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.selectUser(1L);Pros: full control over SQL, high performance, simple model.
Cons: need to write SQL manually, lack of automatic caching, more code.
3. JPA (Java Persistence API) — the standard
JPA is a specification, not an implementation. It defines a standard way of ORM through annotations and EntityManager. The most popular implementation is Hibernate, but there are also EclipseLink and OpenJPA. JPA allows you to easily switch between providers.
Example: EntityManager
@PersistenceContextprivate EntityManager em;
public User findUser(Long id) { return em.find(User.class, id);}
public List<User> findByName(String name) { return em.createQuery("SELECT u FROM User u WHERE u.name = :name", User.class) .setParameter("name", name) .getResultList();}Pros: standardization, portability, integration with Spring.
Cons: specification limitations, complex queries require JPQL.
4. Spring Data JPA — convenient
Also in library
CLI frameworks for TypeScript: complete overview and usage examples
PHP Application Monitoring: A Complete Guide to Tools and Libraries
Jetpack Compose for Kotlin: Complete Guide with Examples