Data Engineering/JAVA

JDBC, ODBC, ORM, JPA에 대해 알아보기

cstory-bo 2023. 12. 26. 22:08

JDBC

JDBC : Java Database Connectivity

 

만약 표준 인터페이스가 없다면 어떨까?

아마 각 데이터베이스마다 어떤 함수를 써야하는 지 찾아보며 수정해야할 것이다.

 

그래서사용자가 자바에서 제공하는 표준인터페이스에서 정의된 클래스와 함수를 데이터베이스의 종류와 상관없이 사용하고

사용하고자 하는 DB에 따라 라이브러리만 바꾸면

JDBC에서 해당 DB에 따른 함수를 요청해준다.

 

JDBC는 기본적으로를 상정하고 만들었으며

NoSQL이나 빅데이터 계열은 JDBC를 따르지 않고 독자적인 메소드를 만드는 편이다.

 

ODBC

ODBC : Open Database Connectivity

JDBC가 인기를 얻자 이제는 Java말고 프로그래밍 언어나 운영체제와 상관없이

독립적으로 DBMS를 사용하고자 ODBCDriver가 나왔다.

ORM

객체지향 언어인 JAVA에서 테이블로 구현된 데이터베이스에서 값을 가져오려면

POJO Class(getter, setter 등을 가진 가장 기본적인 클래스) 구현이 필요하다.

 

ORM은 이러한 수고를 덜어주기 위해

관계형 데이터베이스 모델(Relational Model)과 Object 객체를 매핑시켜준다.

 

이로써 굳이 SQL문 없이, 클래스를 구현하지 않고

오히려 더욱 직관적인 자바 코드로만 데이터를 다를 수 있다.

 

JPA

자바 ORM기술에 대한 API 표준 명세이다.

한마디로 ORM 사용을 위한 인터페이스들을 모아둔 것이다.

 

Spring Data JPA

JPA 종류 즁 하나로 셋팅이 쉬워 빠르게 사용하기 좋다.

 

우선 Gradle에서 의존성을 추가한다.

dependencies {
    implementation 'mysql:mysql-connector-java:8.0.30'

    compileOnly 'org.projectlombok:lombok:1.18.24'
    annotationProcessor 'org.projectlombok:lombok:1.18.24'
}

 

@하나로 여러 생성자와 getter, setter 등 빠르게 구현할 수 있다.

 

여기서 Entity는 DB table에 매핑되는 클래스이다.


@Entity(name="product")
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
public class Product {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String name;
    @Column(name = "updated_at", columnDefinition = "DATE")
    private LocalDateTime updatedAt;
    private String contents;
    private int price;
}

 

또한 @Query로 직접 작성한 SQL문으로 함수에 매핑시킬 수 있다.

public interface ProductRepository extends CrudRepository<Product, Long> {

    List<Product> findTop10ByOrderByPriceDesc();

    List<Product> findByPriceGreaterThanOrderByPriceDesc(int price);

    @Modifying
    @Transactional
    @Query("UPDATE product p SET p.price = p.price + :plus where id = :id")
    int plusPrice(Long id, int plus);
}

 

 

위에서 구현한 인터페이스로 save, findById, FindByPriceGreaterThan~ 등

SQL문 대신 만들어진 여러 메소드를 사용할 수 있다.

@SpringBootApplication
@Slf4j
public class SpringJpaExApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringJpaExApplication.class, args);
    }

    @Bean
    public CommandLineRunner demo(ProductRepository productRepository) {
        return args -> {
            productRepository.save(new Product(101L, "product101", LocalDateTime.now(), "content101", 101));
            productRepository.save(new Product(102L, "product102", LocalDateTime.now(), "content102", 102));

            log.info("=== all records ===");
            for (Product product : productRepository.findAll()) {
                log.info(product.toString());
            }

            log.info("find by id = 101");
            productRepository.findById(101L).ifPresent(it -> log.info(it.toString()));

            log.info("find top 10 order by price desc");
            for (Product product : productRepository.findTop10ByOrderByPriceDesc()) {
                log.info(product.toString());
            }

            log.info("find by price greater than 10000");
            for (Product product : productRepository.findByPriceGreaterThanOrderByPriceDesc(10000)) {
                log.info(product.toString());
            }

            log.info("plus price + 10000 where id = 101: " + productRepository.plusPrice(101L, 10000));
            log.info("find by id = 101");
            productRepository.findById(101L).ifPresent(it -> log.info(it.toString()));
        };
    }

}