스프링(Spring), 스프링부트(SpringBoot)/스프링부트(SpringBoot) 기초

스프링 부트 핵심 가이드(장정우 지음) - 데이터베이스 연동 2: 프로젝트에 MySQL Community Server 연동, 엔티티 설계 & 리포지토리 인터페이스 설계[코드 수정됨]

개발학생 2025. 7. 21. 16:58
반응형

*책 내용과 다르게, 다음과 같은 환경에서 프로젝트 생성  

 

[Java] 차근차근 Java 설치하기 (JDK17, Window 11)

자바 개발 도구 설치 방법에 대해서 알아보겠습니다. Java17은 LTS(Long Term Support : 장기 지원) 릴리즈로 1년 후까지 기술 지원 및 버그를 개선한 서비스를 제공받을 수 있습니다. 업데이트 버전을 꾸

yungenie.tistory.com

 

[Windows] Spring Tool Suite 4(STS 4) 다운로드 및 설치

STS란?Spring Tool Suite(STS)는 스프링 프로젝트를 생성하고, 개발할 수 있게 해주는 도구입니다. STS 설치 과정에 대해 설명드리겠습니다. 설치 파일 다운로드STS 공식 사이트에서 설치 파일을 다운로

priming.tistory.com

 

MySQL :: Download MySQL Community Server

Select Version: 9.3.0 Innovation 8.4.5 LTS 8.0.42 Select Operating System: Select Operating System… Microsoft Windows Ubuntu Linux Debian Linux SUSE Linux Enterprise Server Red Hat Enterprise Linux / Oracle Linux Fedora Linux - Generic Oracle Solaris mac

dev.mysql.com

  • Gradle

**STS에서 Gradle 프로젝트 생성한 과정 

*** 함께 보면 좋은 글

2025.07.10 - [스프링(Spring), 스프링부트(SpringBoot)/스프링부트(SpringBoot) 기초] - 스프링 부트 핵심 가이드(장정우 지음) - 스프링 부트 개요

 

스프링 부트 핵심 가이드(장정우 지음) - 스프링 부트 개요

1. 스프링 프레임워크자바(Java) 기반 애플리케이션 프레임워크로, 엔터프라이즈급(기업 환경 대상 개발) 애플리케이션을 위한 다양한 기능 제공-> 오픈소스 경량급 애플리케이션 프레임워크로

keep-programming-study.tistory.com

2025.07.11 - [스프링(Spring), 스프링부트(SpringBoot)/스프링부트(SpringBoot) 기초] - 스프링 부트 핵심 가이드(장정우 지음) - 개발에 앞서 알면 좋은 기초 지식

 

스프링 부트 핵심 가이드(장정우 지음) - 개발에 앞서 알면 좋은 기초 지식

1. 서버 간 통신마이크로서비스 아키텍처에서 한 서버가 다른 서버에 통신을 요청하는 것을 의미-> 한 대는 서버/다른 한 대는 클라이언트가 됨 가장 많이 사용되는 방식은 HTTP/HTTPS 방식(TCP/IP, SOA

keep-programming-study.tistory.com

2024.03.26 - [컴퓨터공학 공부/SQLD (SQL 전문가 가이드)] - SQLD 자격증 공부 데이터 모델링의 이해-엔터티, 속성(SQL 전문가가이드)

 

SQLD 자격증 공부 데이터 모델링의 이해-엔터티, 속성(SQL 전문가가이드)

*본 게시물은 2013년도 SQL 전문가 가이드 교재(일명 '노랭이')를 참고하여 공부하고 정리한 게시물입니다 1과목 데이터 모델링의 이해: 제1장 데이터 모델링의 이해 1. 엔터티 1) 정의 업무에서 관

keep-programming-study.tistory.com

2023.06.27 - [자바(JAVA)/JSP 웹 프로그래밍 공부 (성낙현의 JSP 자바 웹 프로그래밍 참고)] - JAVA/JSP 14. 데이터베이스 - 특징, 오라클 설치(Oracle Database 11gR2 Express Edition), 사용자 계정 생성 및 권한 설정

 

JAVA/JSP 14. 데이터베이스 - 특징, 오라클 설치(Oracle Database 11gR2 Express Edition), 사용자 계정 생성 및

1. 데이터베이스의 특징우리가 매일 PC나 스마트폰을 통해 접하는 거의 모든 웹 애플리케이션에서 사용함매일 업데이트되는 뉴스나 날씨 등의 정보는 데이터베이스가 없다면 클라이언트에 전달

keep-programming-study.tistory.com

2025.07.18 - [스프링(Spring), 스프링부트(SpringBoot)/스프링부트(SpringBoot) 기초] - 스프링 부트 핵심 가이드(장정우 지음) - 데이터베이스 연동 1: ORM(Object Relational Mapping) 특징, JPA(Java Persistence API)

 

스프링 부트 핵심 가이드(장정우 지음) - 데이터베이스 연동 1: ORM(Object Relational Mapping) 특징, JPA(Ja

*책 내용과 다르게, 다음과 같은 환경에서 프로젝트 생성 Windows11(윈도우 11) 환경자바 JDK 17 버전 설치 https://yungenie.tistory.com/11 [Java] 차근차근 Java 설치하기 (JDK17, Window 11)자바 개발 도구 설치 방법

keep-programming-study.tistory.com

 

1. 프로젝트에 MySQL Community Server 연동

1) build.gradle에 의존성 추가

dependencies {
	... 생략 ...
    // Spring Boot에서 JPA(Java Persistence API) 기능을 사용하기 위한 의존성 추가
    // -> Spring Data JPA 기능을 통해 리포지토리 인터페이스를 정의하기만 해도 자동으로 CRUD 메서드를 생성해줌
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    // MySQL 데이터베이스와 애플리케이션을 연결해주는 JDBC 드라이버 의존성을 추가(이 커넥터가 있어야만 DB와 통신할 수 있음)
    // -> 'runtimeOnly'는 애플리케이션 실행 시에만 필요한 라이브러리라는 뜻이며, DB에 연결할 때 반드시 있어야 하는 요소
    runtimeOnly 'com.mysql:mysql-connector-j'
}

2) build.gradle 우클릭 후 Gradle -> Refresh Gradle Project 클릭  

build.gradle 우클릭 후 Gradle -> Refresh Gradle Project 클릭

3) application.properties에 코드 추가 - 코드에 잘못된 부분이 있어 수정함(07/23)

application.properties의 위치

# 데이터베이스 연결 정보 설정
# MySQL 서버에 연결할 주소, 포트, DB 이름을 지정. useSSL은 SSL 사용 여부, serverTimezone은 시간대 설정
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useSSL=false&serverTimezone=Asia/Seoul

# DB 접속 시 사용할 사용자 이름
spring.datasource.username=root

# DB 접속 시 사용할 비밀번호
spring.datasource.password=root

# 애플리케이션 실행 시 테이블 자동 생성/수정 여부 설정(운영 환경에서는 validate나 none을 사용)
# - create: 매번 새로 생성
# - update: 기존 테이블과 비교 후 수정 
# - none: 아무 작업도 하지 않음
# - validate: 엔티티와 테이블 구조 일치 여부만 검증
spring.jpa.hibernate.ddl-auto=update

# 실행되는 SQL 쿼리를 콘솔에 출력 (디버깅이나 학습에 유용)
spring.jpa.show-sql=true

spring.application.name=study

# 데이터베이스 연결 정보 설정
# MySQL 서버에 연결할 주소, 포트, DB 이름을 지정. useSSL은 SSL 사용 여부, serverTimezone은 시간대 설정
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useSSL=false&serverTimezone=Asia/Seoul

# DB 접속 시 사용할 사용자 이름
spring.datasource.username=root

# DB 접속 시 사용할 비밀번호
spring.datasource.password=root

# 애플리케이션 실행 시 테이블 자동 생성/수정 여부 설정(운영 환경에서는 validate나 none을 사용)
# - create: 매번 새로 생성
# - update: 기존 테이블과 비교 후 수정 
# - none: 아무 작업도 하지 않음
# - validate: 엔티티와 테이블 구조 일치 여부만 검증
spring.jpa.hibernate.ddl-auto=update

# 실행되는 SQL 쿼리를 콘솔에 출력 (디버깅이나 학습에 유용)
spring.jpa.show-sql=true

4) MySQL Workbench 설치 후 DB 생성

(1) MySQL Workbench 설치 

MySQL Workbench 설치
MySQL Workbench 설치2(로그인 없이)

(2) MySQL Workbench에서 DB 생성

MySQL Workbench 첫 화면
MySQL Workbench에서 DB 생성

2. 엔티티 설계 & 리포지토리 인터페이스 설계 

1) 엔티티 설계(엔티티 클래스 생성) - 코드에 잘못된 부분이 있어 수정함(07/23)

  • @Column에서 많이 사용하는 다른 요소로는 name(칼럼명 설정), length(데이터 최대길이 설정), unique(중복 금지)가 있음 
  • 데이터베이스에서 엔티티를 이용하지 않을 경우, @Transient를 사용
// Product.java
package com.example.demo.jpa.data.entity;

import java.time.LocalDateTime;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

//이 클래스는 JPA 엔티티로 데이터베이스 테이블과 매핑
@Entity
//엔티티가 매핑될 테이블 이름을 명시적으로 지정 (기본값은 클래스 이름)
@Table(name="product")
public class Product {
	// 기본 키(PK)로 지정된 필드. 데이터베이스의 고유 식별자 역할
    @Id
    // ID 값을 자동 생성함. GenerationType.IDENTITY는 DB가 직접 AUTO_INCREMENT 방식으로 생성하도록 함(insert 후에 pk 자동생성)
    // -> IDENTITY외에도 AUTO(기본값, 사용하는 데이터베이스에 맞게 기본값 자동 생성), 
    //    SEQUENCE(Oracle, PostgreSQL 등 시퀀스를 지원하는 DB에서 별도 시퀀스 객체를 생성해 PK값 증가), 
    //    TABLE(키 값을 관리하는 별도 테이블을 생성해 PK값 증가-성능 낮음)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
	private long number;

    // 엔티티 클래스의 필드는 자동으로 테이블 칼럼으로 매핑되므로, 별다른 설정을 하지 않을 경우 @Column을 생략해도 됨
    // 상품 이름 (Null 허용하지 않음)
    @Column(nullable = false)
    private String name;
    
    // 가격 (Null 허용하지 않음)
    @Column(nullable = false)
    private int price;
    
    // 재고 수량 (Null 허용하지 않음)
    @Column(nullable = false)
    private int stock;

    // 상품 생성 일시 (자동 설정할 수 있으나 현재는 수동 할당 전제)
    private LocalDateTime createdAt;

    // 상품 수정 일시
    private LocalDateTime updatedAt;

    // Getter/Setter 메서드는 객체 지향의 캡슐화 원칙을 따름
    // -> 필드에 직접 접근하지 않고 메서드를 통해 값 조회/수정하도록 하여 유연성과 안정성을 높임
	public long getNumber() {
		return number;
	}

	public void setNumber(long number) {
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public int getStock() {
		return stock;
	}

	public void setStock(int stock) {
		this.stock = stock;
	}

	public LocalDateTime getCreatedAt() {
		return createdAt;
	}

	public void setCreatedAt(LocalDateTime createdAt) {
		this.createdAt = createdAt;
	}

	public LocalDateTime getUpdatedAt() {
		return updatedAt;
	}

	public void setUpdatedAt(LocalDateTime updatedAt) {
		this.updatedAt = updatedAt;
	}
}

* Getter/Setter 메서드 자동생성 방법

Getter/Setter 메서드 자동생성 1
Getter/Setter 메서드 자동생성 2

2) 리포지토리 인터페이스 설계

  • Spring Data JPA가 제공하는 JpaRepository 인터페이스를 기반으로 더욱 쉽게 사용할 수 있는 아키텍처 제공
    -> JpaRepository를 상속하는 인터페이스를 생성하여 기존의 다양한 메서드를 활용
  • 엔티티가 생성한 테이블에 접근하는 데 사용

(1) 리포지토리 인터페이스 생성

  • 접근하려는 테이블과 매핑되는 엔티티에 대한 인터페이스를 생성하고, JpaRepository를 상속받으면 됨
package com.example.demo.jpa.data.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.demo.jpa.data.entity.Product;

public interface ProductRepository extends JpaRepository<Product, Long> {
  // Product 엔티티에 대한 CRUD + customMethod 사용 가능
}
  • 이때 위 코드에서 ctrl을 누르고 JpaRepository를 클릭하면 제공하는 기본 메서드 정보를 확인할 수 있음
/*
 * Copyright 2008-2025 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.jpa.repository;

import jakarta.persistence.EntityManager;

import java.util.List;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.data.repository.ListPagingAndSortingRepository;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.QueryByExampleExecutor;

/**
 * JPA specific extension of {@link org.springframework.data.repository.Repository}.
 *
 * @author Oliver Gierke
 * @author Christoph Strobl
 * @author Mark Paluch
 * @author Sander Krabbenborg
 * @author Jesse Wouters
 * @author Greg Turnquist
 * @author Jens Schauder
 */
@NoRepositoryBean
public interface JpaRepository<T, ID>
		extends ListCrudRepository<T, ID>, ListPagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	/**
	 * Flushes all pending changes to the database.
	 */
	void flush();

	/**
	 * Saves an entity and flushes changes instantly.
	 *
	 * @param entity entity to be saved. Must not be {@literal null}.
	 * @return the saved entity
	 */
	<S extends T> S saveAndFlush(S entity);

	/**
	 * Saves all entities and flushes changes instantly.
	 *
	 * @param entities entities to be saved. Must not be {@literal null}.
	 * @return the saved entities
	 * @since 2.5
	 */
	<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

	/**
	 * Deletes the given entities in a batch which means it will create a single query. This kind of operation leaves JPAs
	 * first level cache and the database out of sync. Consider flushing the {@link EntityManager} before calling this
	 * method.
	 * <p>
	 * It will also NOT honor cascade semantics of JPA, nor will it emit JPA lifecycle events.
	 *
	 * @param entities entities to be deleted. Must not be {@literal null}.
	 * @deprecated Use {@link #deleteAllInBatch(Iterable)} instead.
	 */
	@Deprecated
	default void deleteInBatch(Iterable<T> entities) {
		deleteAllInBatch(entities);
	}

	/**
	 * Deletes the given entities in a batch which means it will create a single query. This kind of operation leaves JPAs
	 * first level cache and the database out of sync. Consider flushing the {@link EntityManager} before calling this
	 * method.
	 * <p>
	 * It will also NOT honor cascade semantics of JPA, nor will it emit JPA lifecycle events.
	 *
	 * @param entities entities to be deleted. Must not be {@literal null}.
	 * @since 2.5
	 */
	void deleteAllInBatch(Iterable<T> entities);

	/**
	 * Deletes the entities identified by the given ids using a single query. This kind of operation leaves JPAs first
	 * level cache and the database out of sync. Consider flushing the {@link EntityManager} before calling this method.
	 *
	 * @param ids the ids of the entities to be deleted. Must not be {@literal null}.
	 * @since 2.5
	 */
	void deleteAllByIdInBatch(Iterable<ID> ids);

	/**
	 * Deletes all entities in a batch call.
	 */
	void deleteAllInBatch();

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link jakarta.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 * @deprecated use {@link JpaRepository#getReferenceById(ID)} instead.
	 */
	@Deprecated
	T getOne(ID id);

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link jakarta.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 * @deprecated use {@link JpaRepository#getReferenceById(ID)} instead.
	 * @since 2.5
	 */
	@Deprecated
	T getById(ID id);

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link jakarta.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 * @since 2.7
	 */
	T getReferenceById(ID id);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example);

	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
  • JpaRepository의 상속 구조

JpaRepository의 상속 구조

(2) 리포지토리 메서드의 생성 규칙

findBy, readBy, getBy  조회 시작 키워드 
And, Or  조건 연결
Is, Equals  정확히 일치
Between 범위 조건
LessThan, GreaterThan 비교 조건
Like, Containing, StartsWith, EndsWith 문자열 검색
In, NotIn 리스트 포함 여부
IsNull, IsNotNull null 여부
OrderBy + 필드명 + Asc/Desc  정렬

 

반응형