본문 바로가기

카테고리 없음

JPA를 활용한 CRUD

 

 

0. 프로젝트 생성과 작업환경 설정

    pom.xml

 pom.xml은  Maven의 빌드 정보를 담고 있는 파일로, POM(Project Object Model)을 설정하는 부분으로 프로젝트 내 빌드 옵션을 설정하는 부분

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.7.4</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>JpaCrud</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>JpaCrud</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <java.version>11</java.version>
   </properties>
   
   <dependencies>
   		<!-- spring boot starter web -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

   		<!-- spring boot starter tomcat -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-tomcat</artifactId>
         <scope>provided</scope>
      </dependency>
      
   		<!-- spring boot starter test -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      
      <!-- jstl :자바 서버 페이지 표준 태그 라이브러리 웹 개발 플랫폼을 위한 컴포넌트 모음  -->
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>jstl</artifactId>
      </dependency>
      
      <!-- Tomcat Embed Jasper -->
      <dependency>
         <groupId>org.apache.tomcat.embed</groupId>
         <artifactId>tomcat-embed-jasper</artifactId>
      </dependency>
      
      <!-- Spring boot devtool : Spring boot에서 제공하는 개발 편의를 위한 모듈 // 코드가 변경되면 자동으로 어플리케이션을 재구동한다. -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-devtools</artifactId>
         <optional>true</optional>
      </dependency>
      
      <!-- mariadb-java-client -->
      <dependency>
         <groupId>org.mariadb.jdbc</groupId>
         <artifactId>mariadb-java-client</artifactId>
         <version>3.0.6</version>
      </dependency>
		
		<!-- mybatis : SQL 매퍼(Mapper) 프레임워크 -->
      <dependency>
         <groupId>org.mybatis.spring.boot</groupId>
         <artifactId>mybatis-spring-boot-starter</artifactId>
         <version>2.2.2</version>
      </dependency>
      
      <!-- jpa -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      
      <!-- lombok -->
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
      </dependency>
      
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>

 

 

 

application.properties

 # 서버 port번호 설정
server.port = 8083

 # jsp파일은 Springboot의 templates폴더 안에서 작동하지 아니함
 # view단의 경로및 기본 확장자 지정
spring.mvc.view.prefix = /WEB-INF/views/
spring.mvc.view.suffix =  .jsp

 # Spring MVC HiddenMethod // delete, put 등 메서드를 사용할 수 있다.
spring.mvc.hiddenmethod.filter.enabled=true

 # JDBC연동관련 
spring.datasource.driverClassName = org.mariadb.jdbc.Driver
spring.datasource.url = jdbc:mariadb://localhost:3306/db01
spring.datasource.username = root
spring.datasource.password = 1234

 # spring.jpa.hibernate.ddl-auto : JPA의 Database 초기화 전략
 #update : 변경된 스키마를 적용
spring.jpa.hibernate.ddl-auto=update

 # application.properties를 사용할경우 true
spring.jpa.properties.hibernate.format_sql=true

 # Hibernate가 DB에 수행하는 모든 쿼리문을 콘솔에 출력
spring.jpa.properties.hibernate.show-sql=true

 # logging.level.{패키지 경로}를 통해 로깅 레벨을 결정할 수 있음
logging.level.org.hibernate.type.descriptor.sql=DEBUG
logging.level.org.hibernate.SQL=DEBUG


lombok (롬복) 설치

 

 

 

 

프로젝트 > Properties > Project Fecets

자바 버전 확인

 

 

 

1. MVC 구조

 

  • 클라이언트 : 앞단을 담당하는 jsp와
  • Controller : 요청을 받아 알맞은 결과값을 처리하고 결과를 리턴
  • Repository (Interface) :   JpaRepository<MemberEntity클래스를 통해 DB와 소통을 가능케 하고 관련된 메서드를 제공한다.
  • Entity : Model, 애플리케이션을 구성 하는 데이터의 자료형을 규정, 해당코드에서는 컬럼값에 대한 정의를 한다.

 

1_1. MemberController

package com.example;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
@RestController
@RequiredArgsConstructor
@RequestMapping("/")
public class MemberController {
	
	@Autowired
   private final MemberRepository memberRepository ;
   
   @PersistenceContext
    private EntityManager entityManager;
   
   // == UPDATE
   
   @GetMapping("update")
    public String updateMember(@RequestParam(value = "name") String name, @RequestParam(value = "pwd") String pwd) {
        if(memberRepository.findById(name).isEmpty()) { // 값 존재여부 확인
            return "입력한 " + name + "이 존재하지 않습니다";
        } else {
           memberRepository.save(MemberEntity.builder().name(name).pwd(pwd).build());
            return name + "의 비밀번호를  " + pwd + "로 변경 완료";
        }
    }
   
   //==== DELETE

    @GetMapping("delete")
    public String deleteMember(@RequestParam(value = "name") String name) {
        if(memberRepository.findById(name).isEmpty()) { // 값 존재여부 확인
            return "입력한 " + name + "이 존재하지 않습니다";
        } else {
           memberRepository.delete(MemberEntity.builder().name(name).build());
            return name + " 삭제 완료";
        }
    }
    
   // === CREATE
   
    @GetMapping("insert")
    public String insertMember(@RequestParam(value = "name") String name, @RequestParam(value = "pwd") String pwd) {
        if(memberRepository.findById(name).isPresent()) {
            return "동일한 이름이 이미 있습니다";
        } else {
           MemberEntity entity = MemberEntity.builder().name(name).pwd(pwd).build();
            memberRepository.save(entity);
            return "이름 : " + name + " 비밀번호 : " + pwd + "으로 추가 되었습니다";
        }
    }
    
    
    
//    ==== READ ====

    @GetMapping("search")
    public String searchAllMember() {
        return memberRepository.findAll().toString();
    }

    @GetMapping("searchParam")
    public String searchParamMember(@RequestParam(value = "name") String name) {
        List resultList = entityManager.createQuery("select pwd from member where name=:name")
                                       .setParameter("name", name)
                                       .getResultList();
        return resultList.toString();
    }
//
//    @GetMapping("searchParamRepo")
//    public String searchParamRepoMember(@RequestParam(value = "name") String name) {
//        return memberRepository.searchParamRepo(name).toString();
//    }

}

 

 

1_2. MemberRepository 

package com.example;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface MemberRepository extends JpaRepository<MemberEntity, String> {
    @Query(value = "select name, id, pwd from member where name = :name", nativeQuery=true)
       List<MemberEntity> searchParamRepo(@Param("name") String name);

   }

 

1_3. MemberEntity

package com.example;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity(name="member")
public class MemberEntity {
   @Id
    @Column(nullable = false, unique = true)
    private String name;

   @Column(nullable = false, unique = true)
    private int id;
   
    @Column(nullable = false)
    private String pwd;
}

 

 

 

2. 기능 별(CRUD)

 

2_1. R (Select)

read는 클라이언트의 요청에 따라, DB의 정보를 조회하여 결과값을 반환한다.

index(Client)

	<!-- READ  -->
	<h3>READ</h3>
   <a href="search">All serach</a><br/><br/>
   <a href="searchParam?name=AAA">AAA의 비밀번호 찾기</a><br/><br/>

 

//    ==== READ ====

    @GetMapping("search")
    public String searchAllMember() {
        return memberRepository.findAll().toString();
    }

    @GetMapping("searchParam")
    public String searchParamMember(@RequestParam(value = "name") String name) {
        List resultList = entityManager.createQuery("select pwd from member where name=:name")
                                       .setParameter("name", name)
                                       .getResultList();
        return resultList.toString();
    }

 

findAll()

DB에 접근하여 관려한 모든 값을 데이터로 가져와 반환한다.

https://wakestand.tistory.com/754

 

JPA findAll() 사용 시 정렬하여 반환하는 방법

List list명 = repository명.findAll(Sort.by(Sort.Direction.DESC/ASC, "기준컬럼명")); JPA에서 findAll() 메소드를 사용하는 경우 특정 컬럼을 기준으로 정렬을 해서 결과를 받고 싶었는데 sort를 지원하기 때..

wakestand.tistory.com

 

https://data-make.tistory.com/614

 

[JPA] JPQL Query 정리

| JPQL(Java Persistence Query Language) - 테이블이 아닌 엔티티 객체를 대상으로 검색하는 객체지향 쿼리 - SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않음 - JPA는 JPQL을 분석한 후 적절한 SQL을..

data-make.tistory.com

 

 

 

 

2_2 Create (insert)

index.jsp

 

   <!-- CREATE -->
	<h3>CREATE</h3>
   <a href="insert?name=AAA&pwd=33">AAA넣기</a><br/><br/>
   <a href="insert?name=GGG&pwd=33">GGG넣기</a><br/><br/>
   <a href="insert?name=CCC&pwd=33">CCC 넣기</a><br/><br/>
   <a href="insert?name=강물이&pwd=33">강물이넣기</a><br/><br/>

Controller.jsp

   // === CREATE
   
    @GetMapping("insert")
    public String insertMember(@RequestParam(value = "name") String name, @RequestParam(value = "pwd") String pwd) {
        if(memberRepository.findById(name).isPresent()) {
            return "동일한 이름이 이미 있습니다";
        } else {
           MemberEntity entity = MemberEntity.builder().name(name).pwd(pwd).build();
            memberRepository.save(entity);
            return "이름 : " + name + " 비밀번호 : " + pwd + "으로 추가 되었습니다";
        }
    }


findbyId() 

https://velog.io/@eden/JPA-%EC%97%90%EC%84%9C-getById-vs-findById

 

JPA 에서 getById vs findById

문제점 평소 JPA를 사용하면서 getById와 findById를 혼용해서 사용 하였다. 명확한 차이점을 이해하지 못하고 혼용해서 사용했기에 이번 기회에 알아보려고 한다. getById vs findById 1.SimpleJpaRepository.getB

velog.io

https://bcp0109.tistory.com/325

 

JPA 의 getById() vs findById()

1. Overview JPA 를 사용할 때 ID 값으로 엔티티를 가져오는 두 가지 메소드가 존재합니다. 비슷하지만 다른 이 두가지 메소드의 차이점에 대해서 알아봅시다. 1.1. getById @Override public T getById(ID id) {..

bcp0109.tistory.com

 

isPresent()

https://sin0824.tistory.com/25

 

[Java] Optional<T> isPresent(), ifPresent() 사용하기

Optional을 사용하면 예상치 못한 NullPointerException 예외를 제공되는 메소드로 간단히 회피할 수 있다. 즉, 복잡한 조건문 없이도 널(null) 값으로 인해 발생하는 예외를 처리할 수 있게 된다. 1. isPrese

sin0824.tistory.com

 

save()

https://minkukjo.github.io/framework/2020/07/05/Spring-130/

 

Spring Data JPA - save()

Spring Data JPA

minkukjo.github.io

 

https://web-km.tistory.com/46

 

[Spring Data Jpa] JpaRepository save() 메서드 주의 사항

오늘은 JpaRepository 인터페이스의 메서드 중 주의하여 사용해야 할 save에 대해 알아보겠습니다. 우리가 ORM 프레임워크인 JPA와 Spring을 연계하여 사용할 때 Spring Data에서 지원하는 JpaRepository 인터페

web-km.tistory.com

 

 

2_3. Update (update)

index.jsp

   <!-- UPDATE  -->
	<h3>UPDATE</h3>
   <a href="update?name=AAA&pwd=11">AAA비밀번호 바꾸기</a><br/><br/>
   <a href="update?name=AAA&pwd=99">AAA 비밀번호 바꾸기</a><br/><br/>
   // == UPDATE
   
   @GetMapping("update")
    public String updateMember(@RequestParam(value = "name") String name, @RequestParam(value = "pwd") String pwd) {
        if(memberRepository.findById(name).isEmpty()) { // 값 존재여부 확인
            return "입력한 " + name + "이 존재하지 않습니다";
        } else {
           memberRepository.save(MemberEntity.builder().name(name).pwd(pwd).build());
            return name + "의 비밀번호를  " + pwd + "로 변경 완료";
        }
    }

 

 

 

 

 

 

 

2_4.Delete (Delete)

index.jsp

	<!-- DELETE  -->   
	<h3>READ</h3>
   <a href="delete?name=CCC">CCC 삭제</a><br/><br/>
 //==== DELETE

    @GetMapping("delete")
    public String deleteMember(@RequestParam(value = "name") String name) {
        if(memberRepository.findById(name).isEmpty()) { // 값 존재여부 확인
            return "입력한 " + name + "이 존재하지 않습니다";
        } else {
           memberRepository.delete(MemberEntity.builder().name(name).build());
            return name + " 삭제 완료";
        }
    }

 

 

delete()

https://hwanchang.tistory.com/7

 

Spring Data JPA 사용 시 deleteById 와 delete 의 차이

Spring Data 란? Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store...

hwanchang.tistory.com

 

isEmpty()

https://hianna.tistory.com/531

 

[Java] isEmpty() 와 isBlank()의 차이

java.lang.String 클래스에는 isEmpty() 메소드와 isBlank() 메소드가 있습니다. (JAVA 11 이후 버전 기준) 두 개의 메소드 모두 문자열이 empty string인지 체크합니다. 하지만, 약간의 차이가 있습니다. 1. isEm..

hianna.tistory.com