backend
  • README
  • DOCS
    • Java Docs
    • Servlet Docs
    • JSP Docs
    • DB & SQL Docs
    • Spring Boot Docs
    • Spring Security Docs
    • AWS Docs
  • 설치하기
    • Intellij 설정
  • 자바
    • 01 Java란?
    • 02 자바 시작하기
    • 03 자료형과 연산자
    • 04 제어문
    • 05 메소드
    • 06 클래스 기초
      • Static 보충자료
      • 패키지 보충자료
    • 07 객체지향 프로그래밍
    • 08 클래스 더 알아보기
      • 열거형 ENUM 보충자료
    • 09 클래스와 자료형
      • 다형성 보충자료
      • 제네릭 보충자료
    • 10 컬렉션 프레임워크
      • 컬렉션 프레임워크 보충자료
    • 11 람다식과 함수형 프로그래밍
      • 람다식 보충자료
    • 12 오류 대비하기
      • 오류 보충자료
    • 13 멀티태스킹
      • 멀티태스킹 보충자료
    • 교재보충
      • java.lang
  • 스프링
    • 서블릿, JSP
      • 05 Servlet(서블릿)
        • 서블릿 보충자료
        • 서블릿 추가코드
        • XML, YAML, JSON
      • 06 JSP(자바 서버 페이지)
        • JSP 보충자료
      • 07 JSTL(JSP 스탠다드 태그 라이브러리)
        • JSTL 보충자료
      • 08 Cookie(쿠키), Session(세션)
      • 09 서블릿,필터,리스너
        • 서블릿,필터,리스너 보충자료
      • 11 도서관리 프로젝트 실습
    • Spring Boot
      • 01 스프링 등장 배경, 객체지향
        • 스프링 등장 배경, 객체지향 보충자료
      • 02 IOC(제어의 역전), DI(의존성 주입)
        • IOC 보충자료
        • DI 보충자료
      • 03 스프링 구조
        • 스프링 구조 보충설명
      • 04 테스트코드 실습
      • 05 스프링 빈 설정
        • 스프링 빈 설정 보충자료
      • 06 싱글톤
        • 싱글톤 보충 자료
      • 07 스프링 빈 자동설정
        • 스프링 빈 자동설정 보충자료
      • 08 빈 생명주기
        • 빈 생명주기 보충자료
      • 09 빈 스코프
        • 빈 스코프 보충자료
      • 10 스프링 MVC
        • 스프링 MVC 보충자료
        • 데이터베이스 연동에 필요한 부분
      • 11 Validation(검증)
        • Validation(검증) 보충자료
      • 12 Bean Validation(빈검증)
        • Bean Validation(빈검증) 보충자료
      • 13 예외처리
        • 예외처리 보충자료
      • 14 타입변환
      • 15 JDBC(Java Database Connectivity)
      • 16 커넥션풀
      • 17 트랜잭션
        • 트랜잭션 보충자료
      • 18 JDBC 템플릿 활용
      • 19 MyBatis
      • 20 JPA(Java Persistence API)
      • 22 게시판 프로젝트 실습
    • Spring Security
      • 보안(Security)
      • Spring Security
      • 2. Spring Security 알아보기
        • 보안 위협 실제 사례와 방어 전략
      • 3. Spring Security 기본 동작 흐름
      • 4. Spring Security로 인증 권한 추가하기
        • Spring Security의 인증 및 인가
      • 5. Spring Security에서 세션 관리하기
        • 세션(Session)과 쿠키(Cookie) 비교, 토큰(Token)과의 관계
        • 해싱 및 해싱알고리즘
        • base64
      • 6. Spring Security 악용 보호
        • SameSite
      • 7. Spring Security로 인가 권한 추가하기
      • 8. Bcrypt(비크립트) 암호화
      • OAuth2 적용하기
  • 네트워크
    • HTTP
    • OSI 7계층
  • DB&SQL
    • 01 Database(데이터베이스)와 SQL 개요
    • 02 관계형 모델
    • 03 집합
    • 04 JOIN 연산
    • 05 MySQL
      • 세이브포인트
      • DBeaver, Mysql 오토커밋 설정 관련
    • 06 SQL 기초
      • 예시데이터 쿼리문
    • 07 SQL 실습
      • 실습 스키마
    • 08 Join 활용
      • 실습스키마
    • 09 SQL 활용
      • 실습스키마
    • 10 정규화
      • 실습 스키마
    • 데이터타입
    • 예시 프로젝트 스키마 구성
  • AWS
    • SSL 연결하기
    • 보충설명
Powered by GitBook
On this page
  1. 스프링
  2. Spring Boot

20 JPA(Java Persistence API)

p396 - build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.3.4'
	id 'io.spring.dependency-management' version '1.1.6'
}

group = 'spring.jdbc'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(21)
	}
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
//	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.mysql:mysql-connector-j'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

	testCompileOnly 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'

	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3' // MyBatis 의존성 추가
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // JPA 추가

}

tasks.named('test') {
	useJUnitPlatform()
}

p 397 - src/reousrces/application.properties

# Application Name
spring.application.name=template

# MySQL Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=1234
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

# HikariCP Configuration
spring.datasource.hikari.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.pool-name=HikariPool

# MyBatis
mybatis.type-aliases-package=spring.jdbc.template.domain
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.spring.jdbc.template.mybatis=trace

# JPA
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.orm.jdbc.bind=TRACE

p398 - src/main/java/spring/jdbc/template/domain/User

@Getter @Setter
@Entity
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userIdx;
    @Column(name="user_id", length = 255)
    private String userId;
    @Column(name = "age")
    private int age;

    public User(){}

    public User(String userId, int age) {
        this.userId = userId;
        this.age = age;
    }
}

p399, 400 - src/main/java/spring/jdbc/template/repository/UserJpaRepositoryImpl

@Slf4j
@Repository
@Transactional
public class UserJpaRepositoryImpl implements UserRepository{

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public User save(User user) {
        entityManager.persist(user);
        return user;
    }

    @Override
    public void update(Long userIdx, UserUpdateDto userUpdateDto) {
        User user = entityManager.find(User.class, userIdx);
        user.setUserId(userUpdateDto.getUserId());
        user.setAge(userUpdateDto.getAge());
    }

    @Override
    public Optional<User> findByIdx(Long userIdx) {
        User user = entityManager.find(User.class, userIdx);
        return Optional.ofNullable(user);
    }

    @Override
    public List<User> findAll(UserListDto dto) {
        // User는 domain 안에 User 클래스를 말함
        String jpql = "SELECT u FROM User u WHERE 1=1";
        StringBuilder queryBuilder = new StringBuilder(jpql);

        if (dto.getUserId() != null && !dto.getUserId().isEmpty()) {
            queryBuilder.append(" AND u.userId = :userId");
        }
        if (dto.getMinAge() != null) {
            queryBuilder.append(" AND u.age >= :minAge");
        }
        if (dto.getMaxAge() != null) {
            queryBuilder.append(" AND u.age <= :maxAge");
        }

        TypedQuery<User> query = entityManager.createQuery(queryBuilder.toString(), User.class);

        if (dto.getUserId() != null && !dto.getUserId().isEmpty()) {
            query.setParameter("userId", dto.getUserId());
        }
        if (dto.getMinAge() != null) {
            query.setParameter("minAge", dto.getMinAge());
        }
        if (dto.getMaxAge() != null) {
            query.setParameter("maxAge", dto.getMaxAge());
        }

        return query.getResultList();
    }
}

p401 ~ 403 - src/test/java/spring/jdbc/template/repository/UserJpaRepositoryImplTest

@SpringBootTest
@Transactional
public class UserJpaRepositoryImplTest {

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private UserJpaRepositoryImpl userJpaRepository;

    @BeforeEach
    public void setUp() {
        // 테스트 데이터를 추가합니다.
        User user1 = new User("user1", 25);
        User user2 = new User("user2", 30);
        User user3 = new User("user3", 35);
        entityManager.persist(user1);
        entityManager.persist(user2);
        entityManager.persist(user3);
    }

    @Test
    public void testSave() {
        // 새로운 사용자 저장
        User newUser = new User("user4", 28);
        userJpaRepository.save(newUser);

        // 저장된 사용자 검증
        UserListDto dto = new UserListDto("user4", null, null);
        List<User> users = userJpaRepository.findAll(dto);
        assertThat(users).hasSize(1);
        assertThat(users.get(0).getUserId()).isEqualTo("user4");
        assertThat(users.get(0).getAge()).isEqualTo(28);
    }

    @Test
    public void testUpdate() {
        // 사용자 업데이트
        UserUpdateDto updateDto = new UserUpdateDto("updatedUser1", 40);
        Optional<User> userOpt = userJpaRepository.findByIdx(1L);

        userOpt.ifPresent(user -> {
            userJpaRepository.update(user.getUserIdx(), updateDto);

            // 업데이트 검증
            Optional<User> updatedUser = userJpaRepository.findByIdx(user.getUserIdx());
            assertThat(updatedUser).isPresent();
            assertThat(updatedUser.get().getUserId()).isEqualTo("updatedUser1");
            assertThat(updatedUser.get().getAge()).isEqualTo(40);
        });
    }

    @Test
    public void testFindAll_noFilters() {
        // 필터가 없는 경우, 모든 사용자가 반환되는지 확인
        UserListDto dto = new UserListDto(null, null, null);
        List<User> users = userJpaRepository.findAll(dto);

        assertThat(users).hasSize(3);
    }

    @Test
    public void testFindAll_withUserId() {
        // 특정 userId로 필터링
        UserListDto dto = new UserListDto("user1", null, null);
        List<User> users = userJpaRepository.findAll(dto);

        assertThat(users).hasSize(1);
        assertThat(users.get(0).getUserId()).isEqualTo("user1");
    }

    @Test
    public void testFindAll_withMinAge() {
        // 최소 나이 조건으로 필터링
        UserListDto dto = new UserListDto(null, 30, null);
        List<User> users = userJpaRepository.findAll(dto);

        assertThat(users).hasSize(2);
        assertThat(users).extracting("userId").containsExactly("user2", "user3");
    }

    @Test
    public void testFindAll_withMaxAge() {
        // 최대 나이 조건으로 필터링
        UserListDto dto = new UserListDto(null, null, 30);
        List<User> users = userJpaRepository.findAll(dto);

        assertThat(users).hasSize(2);
        assertThat(users).extracting("userId").containsExactly("user1", "user2");
    }

    @Test
    public void testFindAll_withMinAndMaxAge() {
        // 최소 및 최대 나이 조건으로 필터링
        UserListDto dto = new UserListDto(null, 25, 35);
        List<User> users = userJpaRepository.findAll(dto);

        assertThat(users).hasSize(3);
        assertThat(users).extracting("userId").containsExactly("user1", "user2", "user3");
    }
}
Previous19 MyBatisNext22 게시판 프로젝트 실습

Last updated 6 months ago