JPA 코드에서 JDBC 코드로 변경하기
이 글에서는 JPA로 작성된 코드를 JDBC로 변경하는 과정을 살펴보겠습니다. JPA는 객체와 데이터베이스 간의 매핑을 자동으로 처리해 주지만, JDBC는 우리가 직접 SQL을 작성해야 하고 데이터베이스와의 연결을 수동으로 처리해야 합니다. 아래에서 JPA 코드를 JDBC로 변경하는 방법을 단계별로 진행해 보겠습니다.
JPA로 작성된 Product 클래스
먼저, JPA를 사용해 작성된 Product 클래스입니다. JPA는 어노테이션을 통해 데이터베이스 테이블과의 매핑을 쉽게 처리할 수 있습니다.
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Enumerated(EnumType.STRING)
private ProductType type;
@ManyToOne
@JoinColumn(name = "teacher_id")
private User teacher;
private Integer count;
}
이 Product 엔티티는 데이터베이스의 product 테이블과 매핑되며, @ManyToOne 관계를 통해 teacher 필드가 User 엔티티와 연관되어 있습니다.
JPA로 작성된 ProductRepository
JPA를 사용하면, 엔티티와 데이터베이스 간의 상호작용을 간단하게 처리할 수 있습니다. 아래는 JPA를 활용하여 작성한 ProductRepository입니다.
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}
위의 코드에서 볼 수 있듯이, ProductRepository는 JpaRepository를 상속받아 간단하게 정의됩니다. JpaRepository는 기본적인 CRUD 메서드를 내장하고 있기 때문에, save, findAll, findById와 같은 메서드를 직접 구현할 필요 없이 즉시 사용할 수 있습니다.
JPA로 작성된 ProductService
JPA를 사용하면 서비스 계층에서도 데이터베이스와의 상호작용을 간편하게 처리할 수 있습니다. 아래는 ProductService 클래스입니다.
@Service
@RequiredArgsConstructor
@Transactional
public class ProductService {
private final ProductRepository productRepository;
private final UserRepository userRepository;
public Long createProduct(final Long userId, final ProductCreateRequest productCreateRequest) {
final User user = userRepository.getById(userId);
final Product product = Product.of(user, productCreateRequest);
final Product savedProduct = productRepository.save(product);
return savedProduct.getId();
}
public ProductResponse findProduct(final Long productId) {
final Product product = productRepository.getById(productId);
return ProductResponse.from(product);
}
public List<ProductResponse> findProducts() {
final List<Product> products = productRepository.findAll();
return ProductResponse.from(products);
}
public void updateProduct(final Long userId,
final ProductUpdateRequest productUpdateRequest,
final Long productId) {
final User user = userRepository.getById(userId);
final Product product = productRepository.getById(productId);
product.update(user,productUpdateRequest);
}
public void deleteProduct(final Long productId) {
productRepository.deleteById(productId);
}
}
ProductRepository에 대한 구현이 없어도 ProductService는 정상적으로 작동합니다. JPA가 내부적으로 SQL 쿼리를 생성하고 실행하기 때문에, 개발자는 비즈니스 로직에만 집중할 수 있는 장점이 있습니다.
JDBC로 변경하기
이제 JPA 기반 코드를 JDBC로 변경하는 방법을 살펴보겠습니다. JDBC는 SQL 쿼리를 직접 작성하고 JdbcTemplate을 사용해 데이터베이스와 상호작용합니다. 저는 다음과 같은 CRUD 메서드를 구현하려고 합니다.
- save: 상품 저장
- findAll: 모든 상품 조회
- findById: 특정 상품 조회
- update: 상품 업데이트
- delete: 상품 삭제
JDBC 기반 ProductRepository 구현
ProductRepository는 JdbcTemplate을 사용해 데이터베이스와 상호작용합니다. 각 메서드는 SQL 쿼리를 사용해 데이터베이스의 데이터를 처리합니다.
@Repository
public class ProductRepository {
private final JdbcTemplate jdbcTemplate;
public ProductRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// save
public Product save(Product product) {
KeyHolder keyHolder = new GeneratedKeyHolder();
String sql = "INSERT INTO product (name, type, teacher_id, count) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(con -> {
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, product.getName());
ps.setString(2, product.getType().name());
ps.setLong(3, product.getTeacher().getId());
ps.setInt(4, product.getCount());
return ps;
}, keyHolder);
Long id = keyHolder.getKey().longValue();
product.setId(id);
return product;
}
// findAll
public List<Product> findAll() {
String sql = "SELECT * FROM product";
return jdbcTemplate.query(sql, (rs, rowNum) -> {
Product product = new Product();
product.setId(rs.getLong("id"));
product.setName(rs.getString("name"));
product.setType(ProductType.valueOf(rs.getString("type")));
User teacher = new User();
teacher.setId(rs.getLong("teacher_id"));
product.setTeacher(teacher);
product.setCount(rs.getInt("count"));
return product;
});
}
// findById
public Product findById(Long id) {
String sql = "SELECT * FROM product WHERE id = ?";
return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {
Product product = new Product();
product.setId(rs.getLong("id"));
product.setName(rs.getString("name"));
product.setType(ProductType.valueOf(rs.getString("type")));
User teacher = new User();
teacher.setId(rs.getLong("teacher_id"));
product.setTeacher(teacher);
product.setCount(rs.getInt("count"));
return product;
}, id);
}
// update
public void update(Long id, Product product) {
String sql = "UPDATE product SET name = ?, type = ?, teacher_id = ?, count = ? WHERE id = ?";
jdbcTemplate.update(sql, product.getName(), product.getType().name(),
product.getTeacher().getId(), product.getCount(), id);
}
// delete
public void delete(Long id) {
String sql = "DELETE FROM product WHERE id = ?";
jdbcTemplate.update(sql, id);
}
}
결론
예전에는 JDBC를 통해 데이터베이스와 직접 통신하는 것이 일반적이었습니다. 현재는 JPA와 같은 ORM(Object-Relational Mapping) 프레임워크가 널리 사용되고 있지만, JDBC를 사용하는 방법을 이해하고 있는 것과 모르는 것은 큰 차이가 있을 것이라고 생각하여 JDBC를 적용해 보았습니다.
'WEB' 카테고리의 다른 글
3N+1 문제와 프록시 강제 초기화 해결 (0) | 2024.10.23 |
---|---|
날씨 API 사용과 리팩토링 (0) | 2024.10.15 |
JPA Update 실패 해결기 (0) | 2024.10.10 |
소프트 딜리트란? (1) | 2024.09.27 |
MDC를 이용한 로깅 도입기 (0) | 2024.09.23 |
@SpringBootTest vs @Mock (0) | 2024.09.12 |
스프링부트의 Tomcat과 Thread Pool (0) | 2024.09.10 |
트랜잭션이란? (0) | 2024.09.05 |