-
Spring Boot | JPA + lombok 사용하기▼ Backend/스프링 (Spring) 2021. 7. 19. 21:50반응형
▶ JPA, 자바 지속성 API (Java Persistence API)
자바 플랫폼 SE와 자바 플랫폼 EE를 사용하는 응용프로그램에서 관계형 데이터베이스의 관리를 표현하는 Java API이다.
▶ lombok(https://projectlombok.org/)
getter, setter 등의 반복 메서드를 자동으로 연결하고 도구를 빌드하여 Java를 향상시키는 Java 라이브러리이다.
테이블 생성 member with mariaDB
CREATE TABLE member ( MBR_SEQ BIGINT(20) NOT NULL AUTO_INCREMENT, ID VARCHAR(200) NULL DEFAULT NULL, PWD VARCHAR(200) NULL DEFAULT NULL, NAME VARCHAR(200) NULL DEFAULT NULL, ADDR_LOAD VARCHAR(300) NULL DEFAULT NULL, REG_ID VARCHAR(200) NULL DEFAULT NULL, REG_DTM DATETIME NULL DEFAULT NULL, MOD_ID VARCHAR(200) NULL DEFAULT NULL, MOD_DTM DATETIME NULL DEFAULT NULL, PRIMARY KEY (MBR_SEQ) USING BTREE )
1. Dependency 추가 (jpa, lombok, mariadb)
Maven의 경우 pom.xml에 추가
<!-- JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- JPA --> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- lombok --> <!-- MariaDB --> <dependency> <groupId>org.mariadb.jdbc</groupId> <artifactId>mariadb-java-client</artifactId> </dependency> <!-- MariaDB -->
gradle의 경우 build.gradle에 추가
dependencies { //Jpa implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //lombok implementation 'org.projectlombok:lombok' //mariaDB implementation 'org.mariadb.jdbc:mariadb-java-client' }
2. 데이터베이스 설정
application.properties
spring.datasource.driverClassName=org.mariadb.jdbc.Driver spring.datasource.url=jdbc:mariadb://localhost:3306/database spring.datasource.username=user spring.datasource.password=pwd!@#
application.yml
spring: datasource: driverClassName: org.mariadb.jdbc.Driver url: jdbc:mariadb://localhost:3306/database username: user password: pwd!@#
3. 재사용될 컬럼을 추상 클래스로 작성
CommonVo.java
import java.time.LocalDateTime; import javax.persistence.Column; import javax.persistence.MappedSuperclass; import org.hibernate.annotations.CreationTimestamp; import lombok.Data; //Getter, Setter Auto Create @Data //공통 매핑 정보가 필요할 때, 부모 클래스에 선언하고 속성만 상속 받아서 사용하고 싶을 때 사용한다. @MappedSuperclass public abstract class CommonVo { // register id private String regId; // modify id private String modId; // register Date time @CreationTimestamp /* 보통 JPA는 SAVE시에 모든 칼럼을 INSERT한다. 그럴 경우, NOT NULL로 설정된 칼럼은 기본값으로 삽입되는것이 아닌 NULL로 삽입을 시도한다. 이로 인해 에러가 발생하는데, 이럴 경우에 아예 쿼리에서 빼버려서 실행이 안되게 만들 수 있다. 쿼리에서 제외된 칼럼은 DB에 지정된 default값으로 삽입이 된다. 특정 칼럼을 제외하고 save하는 방법은 다음과 같다. insertable = false, updatable = false*/ @Column(updatable = false) private LocalDateTime regDtm; // modify Date time @CreationTimestamp private LocalDateTime modDtm; }
4. CommonVo를 상속받은 MemberVo 작성
MemberVo.java
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import com.melon.boot.common.vo.CommonVo; import lombok.Data; //Getter, Setter Auto Create @Data //Table Mapping @Entity(name = "member") public class MemberVo extends CommonVo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long mbrSeq; private String id; private String pwd; private String name; private String addrLoad; }
5. JpaRepository를 상속받은 interface 작성
MemberRepository.java
package com.melon.boot.member.service.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.melon.boot.member.vo.MemberVo; public interface MemberRepository extends JpaRepository<MemberVo, Long> { }
6. Service Class 작성
MemberService.java
import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.melon.boot.member.service.repository.MemberRepository; import com.melon.boot.member.vo.MemberVo; @Service public class MemberService { @Autowired private MemberRepository memberRepository; /* INSERT */ public MemberVo save(MemberVo memberVo) throws Exception { return memberRepository.save(memberVo); } /* SELECT LIST */ public List < MemberVo > findAll() throws Exception { return memberRepository.findAll(); } /* SELECT BY ID */ public Optional < MemberVo > findById(Long mbrSeq) throws Exception { return memberRepository.findById(mbrSeq); } /* UPDATE */ public MemberVo updateById(MemberVo memberVo) throws Exception { Optional < MemberVo > e = memberRepository.findById(memberVo.getMbrSeq()); MemberVo resultMember = null; if (e.isPresent()) { resultMember = memberRepository.save(memberVo); } return resultMember; } /* DELETE */ public void deleteById(Long mbrSeq) throws Exception { memberRepository.deleteById(mbrSeq); } }
7. Controller Class 작성
테스트용으로 하드코딩 샘플 데이터가 들어가 있으니, 화면을 작성하고 실제로 사용할 때에는 샘플 데이터를 지우고 객체를 받아 사용한다.
MemberController.java
import java.time.LocalDateTime; 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 com.melon.boot.member.service.MemberService; import com.melon.boot.member.vo.MemberVo; @Controller @RequestMapping("/member") public class MemberController { @Autowired MemberService memberService; @GetMapping("/insert") public void insertMember() throws Exception { try { MemberVo memberVo = new MemberVo(); memberVo.setId("tester"); memberVo.setPwd("pwd123!@#"); memberVo.setName("tom"); memberVo.setAddrLoad("seoul city"); memberVo.setRegId("reg_id"); memberVo.setModId("mod_id"); memberService.save(memberVo); } catch (Exception e) { e.printStackTrace(); } } @GetMapping("/selectList") public void selectMemberList() throws Exception { try { memberService.findAll(); } catch (Exception e) { e.printStackTrace(); } } @GetMapping("/select") public void selectMember() throws Exception { try { memberService.findById((long) 1); } catch (Exception e) { e.printStackTrace(); } } @GetMapping("/update") public void updateMember() throws Exception { try { MemberVo memberVo = new MemberVo(); memberVo.setMbrSeq((long) 1); memberVo.setId("update tester"); memberVo.setPwd("update pwd123!@#"); memberVo.setName("update name"); memberVo.setAddrLoad("update seoul city"); memberVo.setRegId("update reg_id"); memberVo.setModId("update mod_id"); memberVo.setModDtm(LocalDateTime.now()); memberService.updateById(memberVo); } catch (Exception e) { e.printStackTrace(); } } @GetMapping("/delete") public void deleteMember(MemberVo memberVo) throws Exception { try { memberService.deleteById((long) 1); } catch (Exception e) { e.printStackTrace(); } } }
8. 테스트 URL
- /member/insert
- /member/selectList
- /member/select
- /member/update
- /member/delete
쿼리 실행 로그를 콘솔에 출력
application.properties
#쿼리 로그 설정 spring.jpa.show-sql=true #SQL문을 보기 좋게 출력 spring.jpa.properties.hibernate.format_sql=true #바인딩되는 파라미터 값 출력 logging.level.org.hibernate.type.descriptor.sql=trace
application.yml
spring: jpa: show-sql: true #쿼리 로그 설정 properties: hibernate: format_sql: true #SQL문을 보기 좋게 출력 logging: level: org: hibernate: type: descriptor: sql: trace #바인딩되는 파라미터 값 출력
그 외에 이름 안에서 지원되는 키워드
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2 Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2 Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = 1? Between findByStartDateBetween … where x.startDate between 1? and ?2 LessThan findByAgeLessThan … where x.age < ?1 LessThanEqual findByAgeLessThanEqual … where x.age ⇐ ?1 GreaterThan findByAgeGreaterThan … where x.age > ?1 GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1 After findByStartDateAfter … where x.startDate > ?1 Before findByStartDateBefore … where x.startDate < ?1 IsNull findByAgeIsNull … where x.age is null IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null Like findByFirstnameLike … where x.firstname like ?1 NotLike findByFirstnameNotLike … where x.firstname not like ?1 StartingWith findByFirstnameStartingWith … where x.firstname like ?1(parameter bound with appended %) EndingWith findByFirstnameEndingWith … where x.firstname like ?1(parameter bound with prepended %) Containing findByFirstnameContaining … where x.firstname like ?1(parameter bound wrapped in %) OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc Not findByLastnameNot … where x.lastname <> ?1 In findByAgeIn(Collection<Age> ages) … where x.age in ?1 NotIn findByAgeNotIn(Collection<Age> age) … where x.age not in ?1 True findByActiveTrue() … where x.active = true False findByActiveFalse() … where x.active = false IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)
직접 쿼리를 작성하여 사용할 경우 @Query 어노테이션을 사용한다.
// 트랜잭션 @Transactional // @Modifying 어노테이션은 @Query 어노테이션으로 작성된 수정, 삭제 쿼리 메소드를 사용할 때 필요하다. // 조회 쿼리를 제외하고 데이터에 변경이 일어나는 INSERT, UPDATE, DELETE 쿼리에서 사용한다. @Modifying @Query(value="UPDATE MEMBER SET PWD=:#{#memberVo.pwd} WHERE MEM_SEQ = :#{#memberVo.seq}", nativeQuery = true) public int updateMemberPwd(MemberVo memberVo);
프로젝트 Export Archive File
프로젝트 import, export
Spring Boot | 프로젝트 import, export
import export
kitty-geno.tistory.com
Reference
https://spring.io/projects/spring-data-jpa반응형'▼ Backend > 스프링 (Spring)' 카테고리의 다른 글
Spring Boot | Thymeleaf Layout 공통 Header, Footer 설정하기 (0) 2021.07.22 Spring Boot | lombok 사용 시 Getter, Setter Undefined (1) 2021.07.21 Spring Boot | YAML, YML 적용하기 (1) 2021.07.19 Spring Boot | 프로젝트 Import, Export (0) 2021.07.19 Spring Boot | 웹 프로젝트 만들기 (Thymeleaf, Jar, Gradle, Eclipse) (0) 2021.07.19