JDBC(Java DataBase Connectivity)
자바 언어로 데이터베이스 프로그래밍을 하기 위한 라이브러리
기존의 JDBC는 DB url에 id, pw를 문자열로 입력하기 때문에 보안에 약하고, 어디서 예외가 터질지 몰라서 안정적이지 못하다는 단점이 있었다. 이를 개선한 것이 JPA이다.
JPA는 JAVA ORM(Object Relational Mapping) 기술에 대한 인터페이스이다. ORM은 객체와 데이터베이스의 관계를 맵핑하는 방법이다.
JPA를 구현한 라이브러리가 Hibernate이다. 이 외에도 EclipseLink, DataNucleus, OpenJPA, TopLink 등 여러가지가 있다. 이를 사용하면 JDBC와 비교했을 때 코드가 좀 더 간결해진다. 하지만 이러한 라이브러리를 써도 반복되는 작업이 발생하기 때문에, 스프링 프레임워크에는 그러한 반복 작업들을 대신 관리해주는 레포지토리들이 구현되어 있다. 대표적으로 SimpleRepository가 있다.
따라서 JDBC를 하드코딩할 필요도, Hibernate를 짤 필요도 없이 스프링 데이터 JPA가 제공하는 추상클래스를 상속받아 구현되어 있는 메서드만 호출하면 된다.
새로운 프로젝트를 받는다.
src-main-resources-application.properties는 Spring 프로젝트에 대한 여러가지 설정값을 지정하는 파일로, .yaml로 변환하여 작성한다.
spring:
jpa:
show-sql: true
properties:
format_sql: true
dialect: package org.hibernate.dialect.MySQLDialect
hibernate:
ddl-auto: validate
datasource:
url: jdbc:mysql://localhost:3306/user?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root1234!!
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
url도 제대로 썼고, id와 pw도 문제가 없는데 자꾸 오류가 난다면 들여쓰기가 제대로 되어있는지 확인해볼 필요가 있다. 내가 그렇게 들여쓰기 오류로 db를 연결하지 못하고 한참을 헤멨다..
DB를 연결한 후, UserEntity 오브젝트를 만들어 데이터베이스와 맵핑시킨다.
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity(name="user")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
private String email;
}
@Entity 애너테이션을 달고, 어떤 테이블과 매칭시킬 것인지 테이블명을 적어준다. 프로퍼티로는 해당 테이블의 컬럼값들을 맵핑한다.
이 중 id는 PRIMARY KEY이므로 @Id를 붙이며, 추가로 @GeneratedValue 애너테이션을 붙여준다. GeneratedValue는 strategy 값을 받아 Id가 어떤 방식으로 생성될지를 정해주는데, 이 값은 어떤 DB를 쓰느냐에 따라 달라진다. MySQL을 사용하므로 IDENTITY로 설정해주면 된다. 이 값은 이제부터 MySQL에 의해 auto-generate된다는 뜻이다.
JpaRepository를 상속받는 UserRepository 인터페이스를 만든다(같은 인터페이스기 때문에 구현이 아닌 상속이다). JpaRepository는 UserEntity와 Primary Key의 타입 Long을 받는다.
JpaRepository는 Spring Boot에서 이미 만들어둔 인터페이스로, 이 인터페이스를 구현한 SimpleJPARepository가 존재한다.
public interface UserRepository extends JpaRepository<UserEntity, Long> {
}
Controller를 만들어 테이블의 모든 데이터를 출력하는 메서드를 만들어본다.
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserApiController {
private final UserRepository userRepository;
@GetMapping("/find-all")
public List<UserEntity> findAll(){
return userRepository.findAll();
}
}
UserRepository를 만들어 주입받고 (@RequiredArgsController), UserRepository의 findAll()을 사용해 전체 테이블을 받아온다.
실제 테이블에 저장된 값을 받아오는 것을 확인할 수 있다.
name만 RequestParam으로 받고 나머지는 default 값인 데이터를 저장하려면,
@GetMapping("/name")
public void autoSave(@RequestParam(name="name") String name){
var user = UserEntity.builder().name(name).build();
userRepository.save(user);
}
메서드를 추가해준다. RequestParam이 name을 찾지 못할 경우에는 name 속성을 지정해준다.
이렇게 JPARepository를 호출하면, Hibernate에서 쿼리문이 만들어지고, 이 쿼리문은 JDBC를 통해 데이터베이스에 질의를 날리게 된다.