일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 배열
- 마이크로서비스 아키텍처
- 자료구조
- Repository 테스트
- 낙관락
- Java
- @Version
- 테스트 코드
- 트랜잭션 락
- 공유락
- @Query
- 스네이크 케이스
- DTO
- 파스칼 케이스
- 원시 자료형
- 비링크
- Service 테스트
- Array
- 디자인 패턴
- Controller 테스트
- jvm
- OOP
- do...while
- 비즈니스 로직
- Entity
- 스프링 부트
- 자바
- 배타락
- springDataJpa
- 스터디
- Today
- Total
menuhwang
[Spring Boot] DB (MySql) 사용 본문
DB (MySql) 사용 및 Entity, Repository 작성
서비스를 제공하기 위해서는 데이터를 DB에 저장 (영속화) 해야만 한다.
유저 정보를 저장하여 로그인할 수 있게 한다거나, 게시물 등록, 도메인에 따라 제품, 강의 영상 등록 등등...
Spring Boot에서 DB 연결을 위한 Dependency추가, 설정 방법을 알아보자.
그리고 Entity를 설계하고 Repository, Service를 작성하여 DB에 저장하고 불러오는 방법을 알아보자.
SpringBoot 설정
DB에는 많은 종류가 있다. MySql, MariaDB, MongoDB, Oracle 등등...
이 글에서는 MySql를 사용할 것이다. 다른 DB를 사용하는 경우 DB에 맞춰 Dependency 추가 및 Driver 설정만 잘해준다면 대체로 문제없이 진행할 수 있을 것이다.
Dependency 추가
runtimeOnly 'mysql:mysql-connector-java' // MySql Driver
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // Spring Data JPA
* spring-boot-starter-data-jpa에 spring-boot-starter와 hidernate가 포함되어있음.
application.properties 작성
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/databaseName
spring.datasource.username=user
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.datasource.driver-class-name : 본인이 사용하는 DB Driver에 맞게 작성해주면 된다.
spring.datasource.url : DB 주소를 입력. databaseName에 본인의 데이터베이스 이름으로 바꿔준다.
spring.datasource.username : DB에 접속할 user를 입력.
* root 계정으로 접속하면 모든 접근권한을 가지고 있으므로 편하겠지만, 그만큼 보안에 취약할 것이다. 새로운 계정을 생성하여 사용한다면 권한 설정도 필요할 것이다.
spring.datasource.password : 계정 비밀번호 입력.
spring.jpa.hibernate.ddl-auto
- create : 실행 시 기존 테이블을 지우고 새로 생성한다.
- create-drop : 애플리케이션 종료 시 테이블을 지운다.
- update : SessionFactory(hidernate)가 실행될 때 변경된 스키마를 갱신한다. 기존 데이터는 유지된다.
- validate : 객체를 검사하지만 스키마는 건드리지 않는다. 테이블 정보와 객체의 정보가 다르면 에러 발생.
- none : ddl-auto 기능 사용하지 않음.
spring.jpa.show-sql : 하이버네이트 쿼리문 출력 여부를 설정.
spring.jap.properties.hibernate.format_sql : 하이버네이트 쿼리문을 보기 좋게 포맷팅 하여 출력해주는 설정.
실제 운영시 ddl-auto에 create, create-drop, update를 사용하지 않는다.
스키마가 변경되거나 데이터가 삭제돼 서비스에 큰 문제를 초래할 수 있기 때문이다.
* ddl-auto 옵션을 validate로 설정한 상태에서 스키마가 일치하지않으면 SchemaManagementException: Schema-validation: missing table 에러가 발생한다.
* ddl-auto 옵션을 none으로 설정하고 스키마가 일치하지않은 경우 application은 정상 실행되지만, 쿼리를 날리는 시점에서 SQLSyntaxErrorException 에러가 발생한다.
Entity 설계
Entity는 데이터베이스의 테이블에 대응하는 클래스이다.
데이터베이스에 사용할 테이블과 컬럼을 정의한다.
@Entity
클래스가 Entity임을 명시하는 어노테이션.
Entity클래스는 테이블과 1:1 대응하고, Entity클래스의 인스턴스는 매핑되는 테이블에서 하나의 레코드를 의미한다.
* 레코드란? 데이터베이스에서 하나의 단위로 취급되는 자료의 집합. 하나의 레코드는 테이블의 가로 한 줄로 나타낸다.
레코드 - 해시넷
레코드(record)란 데이터베이스에서 하나의 단위로 취급되는 자료의 집합을 말한다. 하나의 레코드는 디비 테이블(DB table)에서 가로 방향으로 한 줄로 나타낸다. 줄, 행(行, row) 또는 튜플(tuple)이라
wiki.hash.kr
@Table
일반적으로 @Table 어노테이션이 필요하지 않다. 클래스의 이름과 테이블 이름을 다르게 지정하고 싶은 경우 @Table(name = "TableName")이라고 name속성을 설정해주면 된다.
자바의 명명법과 데이터베이스 명명법이 (관례) 다르기 때문에 사용된다.
카멜 케이스, 파스칼 케이스, 스네이크 케이스 : 다양한 표기법
다양한 표기법 코딩을 하다보면 변수명을 지을 때 여러 단어로 작성하게 되는 경우가 있다. 이 때 가독성을 높이기 위해 몇가지 정형화된 표기법들을 사용한다. 카멜 케이스 카멜 케이스의 표
menuhwang.tistory.com
@Id
Entity클래스에는 반드시 PK(Primary Key) 값이 필요하다. @Id 어노테이션이 선언된 필드를 테이블의 PK값으로 사용한다.
@GeneratedValue
보통 @Id 어노테이션과 함께 사용. @GeneratedValue 어노테이션이 적용된 필드 값을 자동으로 생성한다.
필드 값 생성 옵션은 @GeneratedValue(starategy = 설정 옵션) 형태로 설정해줄 수 있다.
- GenerationType.AUTO : @GeneratedValue의 기본 설정값. 데이터베이스에 맞게 자동 생성.
- GenerationType.IDENTITY : 값 생성을 데이터베이스에 위임. 데이터베이스의 AUTO_INCREMENT를 사용.
- GenerationType.SEQUENCE
- GenerationType.TABLE
@Column
@Column 어노테이션도 @Table 어노테이션과 마찬가지로 별다른 설정을 하지 않을 때는 사용하지 않아도 된다.
@Column 어노테이션에 추가로 설정 가능한 속성
- name : 컬럼명을 직접 설정할 때 사용하는 속성. 기본값은 필드명을 사용한다.
- nullable : 레코드 생성 시 컬럼 값에 null 처리가 가능한지 명시하는 속성.
- length : 데이터의 최대 길이 설정.
- unique : 해당 컬럼을 유니크로 설정.
@Column의 설정은 DB에서 설정을 하는 것이다.
nullable을 true로 설정하는 것이 객체 필드 값에 null을 넣을 수 있다는 것은 아니다.
@Transient
Entity 클래스에 존재하는 필드를 DB에서 필요 없을 경우 사용하는 어노테이션
Repository 작성
Spring Data JPA의 JpaRepository를 상속하는 Repository 인터페이스를 생성하면 쿼리문 생성 없이 손쉽게 다양한 메서드를 사용할 수 있다.
Repository 인터페이스 생성
public interface MyRepository extends JpaRepository<MyEntity, PK_Type> {
// ...
}
JpaRepository를 상속받을 때 제너릭스를 입력해줘야 한다. 첫 번째는 이 Repository에서 사용될 Entity 클래스를, 두 번째는 PK_Type 부분에는 Entity의 PK필드의 타입을 입력해야 한다. @Id 어노테이션이 붙은 필드의 타입이 들어가야 하는 것이다.
Repository 작성 규칙
Repository에 메서드를 작성하면 Spring Data JPA에서 알아서 메서드를 만들어준다.
따라서 Repository 인터페이스를 작성하고 따로 구현체를 만들어주지 않아도 된다.
* Repository를 Spring Data JPA에서 JPA 인터페이스를 이용해 메서드를 생성, JPA 구현체인 Hibernate에서 그 메서드를 실행?
하지만, 이 때문에 Repository 작성 시 따라야 할 규칙이 있다.
Spring Data JPA - Reference Documentation
Example 109. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del
docs.spring.io
MyRepository.java
public interface MyRepository extends JpaRepository<MyEntity, Long> {
Optional<MyEntity> findOneByName(String name);
List<MyEntity> findAll();
List<MyEntity> findByName(String name);
List<MyEntity> findByNameContains(String name);
List<MyEntity> findByAgeGreaterThan(int age);
List<MyEntity> findByAgeGreaterThenEqual(int age);
// ...
}
등등 많은 메서드를 만들 수 있지만 꼭 규칙에 맞게 생성해야 하므로 위에 있는 공식문서를 참고하도록 하자.
Service 및 Controller 작성
Service는 Repository를 활용해 비즈니스 로직을 실행하는 계층이다. Repository를 DI(의존성 주입)하여 Service를 작성해보자.
MyService.java
@Service
public class MyService {
private MyRepository myRepository;
@Autowired
public MySerivce(MyRepository myRepository) {
this.myRepository = myRepository;
}
public List<MyEntity> findAll() {
return myRepository.findAll();
}
// ...
}
Service에 Repository를 주입받는다.
주입받은 Repository 메서드를 활용하여 비즈니스 로직 메서드를 작성한다.
MyController.java
@RestController
public class MyController {
private MyService myService;
@Autowired
public MyController(MyService myService) {
this.myService = myService;
}
@GetMapping("/api/myetity")
public List<MyEntity> findAll() {
return myService.findAll();
}
}
Controller에 MyService를 주입한다.
URI에 따라 알맞은 비즈니스 로직(서비스 메서드)을 제공한다.
위 예시에서는 Entity로 응답해주고 있다.
Entity 그대로 응답해주는 방법은 불필요한, 혹은 클라이언트에게 보여주기에는 민감한 정보들이 담겨있을 수 있기 때문에 바람직하지 않다.
Entity에 어노테이션을 붙여 응답 시 제외하도록 하는 방법이 있긴 하지만, ResponseDTO를 따로 생성하여 제공하는 것이 바람직하다.
'스터디 > Spring' 카테고리의 다른 글
[Spring Boot] TDD(Test-Driven-Development) (2/5) (0) | 2022.09.05 |
---|---|
[Spring Boot] 테스트 코드 작성 이유 (1/5) (0) | 2022.09.05 |
[Spring Boot] Spring Data JPA (0) | 2022.08.26 |
[Spring Boot] 로그 남기기 : Logback (0) | 2022.08.24 |
[Spring Boot] Swagger : API 명세 (0) | 2022.08.23 |