Spring Data JPA는 데이터베이스와 객체 간의 매핑을 단순화하고, 데이터베이스 작업을 효율적으로 처리할 수 있도록 설계된 모듈이다. MySQL과 함께 사용하여 데이터베이스를 구성하려면 JPA의 핵심 개념과 자주 사용하는 애노테이션에 대해 깊이 이해하는 것이 중요하다.
먼저, JPA와 Spring Data JPA가 등장하기 전의 데이터베이스 접근 기술과 그 한계, 이를 해결하기 위해 등장한 ORM(Object-Relational Mapping)의 발전 과정을 알아보자.
1. JDBC (Java Database Connectivity)
JDBC는 Java의 표준 데이터베이스 접근 API로, SQL을 직접 작성하고 데이터베이스와의 통신을 수동으로 관리한다. 초기에는 대부분의 애플리케이션이 이 방식을 사용해 데이터베이스 작업을 처리했다. JDBC를 사용하면 SQL 쿼리를 작성하고, 데이터베이스 연결(Connection)을 열고, 쿼리를 실행한 후, 결과(ResultSet)를 처리해야 한다.
그러나 JDBC는 코드가 길고 반복적이며, 데이터베이스와 관련된 비즈니스 로직과 SQL 쿼리가 혼재되어 코드의 유지보수가 어려웠다. 예외 처리나 자원 해제(close 등)도 개발자가 직접 관리해야 했다.
실행 코드
import java.sql.*;
public class JdbcExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydb";
String username = "root";
String password = "password";
String query = "SELECT * FROM users WHERE id = ?";
try (Connection connection = DriverManager.getConnection(url, username, password);
PreparedStatement statement = connection.prepareStatement(query)) {
statement.setInt(1, 1); // 파라미터 설정
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
System.out.println("ID: " + resultSet.getInt("id"));
System.out.println("Name: " + resultSet.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2. MyBatis
JDBC의 반복적이고 지루한 코드 작성을 줄이기 위해 등장한 기술이 MyBatis이다. MyBatis는 SQL 쿼리를 XML로 관리하며, SQL과 Java 코드를 분리해 유지보수를 더 쉽게 만들었다. 또한, 객체와 데이터베이스 간의 매핑을 지원하여 결과를 Java 객체로 직접 반환받을 수 있다. 하지만 여전히 SQL은 직접 작성해야 하며, 복잡한 XML 설정 파일이 필요하다.
XML Mapper 파일 (UserMapper.xml)
<mapper namespace="UserMapper">
<select id="findById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
User 클래스
public class User {
private int id;
private String name;
// Getters and Setters
}
실행 코드
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
public class MyBatisExample {
public static void main(String[] args) throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
try (SqlSession session = sqlSessionFactory.openSession()) {
User user = session.selectOne("UserMapper.findById", 1);
System.out.println("ID: " + user.getId());
System.out.println("Name: " + user.getName());
}
}
}
MyBatis에서 JPA로의 발전 배경
MyBatis는 SQL 중심의 개발을 더 편리하게 만들어줬지만, 여전히 SQL을 직접 작성해야 하고 객체 지향적인 설계와는 거리가 있었다. JPA는 이를 개선하여 객체 중심으로 데이터베이스를 다룰 수 있는 표준을 제공하며, 반복적인 작업을 줄이고 유지보수를 쉽게 만들어준다. 이러한 이유로 JPA는 MyBatis의 한계를 극복하며 등장하게 되었고, 지금은 Java 개발자들이 선호하는 데이터베이스 접근 방식으로 자리 잡았다.
MyBatis는 여전히 복잡한 SQL 쿼리나 데이터베이스 최적화가 필요한 상황에서 강력하다. 반면, JPA는 데이터 중심보다는 객체 중심의 설계와 개발을 필요로 하는 프로젝트에 더 적합하다. 따라서 두 기술은 프로젝트의 성격에 따라 선택하거나, 일부 프로젝트에서는 함께 사용하는 경우도 있다.
3. JPA (Java Persistence API)
JPA는 ORM 기술을 Java 표준화한 API로, 객체와 데이터베이스 간의 매핑을 설정하고 SQL 대신 JPQL(Java Persistence Query Language)을 사용해 데이터를 관리한다.
JPA는 SQL 의존도를 낮추고, 데이터베이스 작업을 더 추상화한다.
User 엔티티
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
private int id;
private String name;
// Getters and Setters
}
persistence.xml
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="my-persistence-unit">
<class>User</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>
실행 코드
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JpaExample {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
User user = em.find(User.class, 1);
System.out.println("ID: " + user.getId());
System.out.println("Name: " + user.getName());
em.getTransaction().commit();
em.close();
emf.close();
}
}
4. Spring Data JPA
Spring Data JPA는 JPA를 더 쉽게 사용할 수 있도록 Spring이 제공하는 모듈이다. 반복적인 코드를 제거하고, CRUD 작업을 메서드 이름만으로 처리할 수 있다. 쿼리를 작성하지 않아도 되고, JPQL, Native Query를 사용할 수 있다.
User 엔티티
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
private int id;
private String name;
// Getters and Setters
}
Repository 인터페이스
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
User findByName(String name);
}
서비스 및 실행 코드
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUserByName(String name) {
return userRepository.findByName(name);
}
}
Spring Data JPA는 가장 높은 수준의 추상화를 제공하여 생산성을 극대화한다. 이전 기술들의 모든 단점을 극복하고, 유지보수성과 확장성을 모두 만족시킨다.
'공부 > Spring' 카테고리의 다른 글
테이블 간의 관계 매핑 애노테이션 (0) | 2025.02.10 |
---|---|
동적 쿼리란? - Querydsl (0) | 2025.02.10 |
WebClient 사용을 위한 배경지식 및 개념 (0) | 2024.03.01 |
객체 지향 프로그래밍 - IoC, DI (0) | 2024.02.27 |
객체 지향 프로그래밍 - 다형성 (0) | 2024.02.25 |