관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[Spring Boot] JPA 추가 및 프로젝트 패키지 분리 본문

웹/Spring Boot

[Spring Boot] JPA 추가 및 프로젝트 패키지 분리

막무가내막내 2020. 4. 7. 22:18
728x90

 

조금씩 시간날 때 지인과 스프링 부트 토이프로젝트를 진행 중에 있습니다. 

막학년이라 할게 넘 많네요. (안드로이드, 알고리즘, 토스, 토익, 졸프, 학교수업 등 ....)  그래서 일단 늦더라도 완성하는거를 목표로 하고 있습니다. 

 

오늘은 jpa 하고 패키지 분리한 것을 간단하게 기록할려합니다. ( 개발환경 세팅 )

 

 

먼저

jpa porm.xml에 추가 후 

 

Failed to read artifact descriptor for org.springframework.boot:spring-boot-starter-data-jpa:jar:2.2.5.RELEASE less... (Ctrl+F1)  
Inspection info: Inspects a Maven model for resolution problems

에러가 발생하였는데 구글링해도 별 답이 안나오고 하나 나온답이 C드라이브 user폴더 m2 의 repository 삭제하고 다시 키라했는데 했다가 프로젝트 터졌습니다.

그래서 다시 클론하고 jpa 관련 porm.xml 에 디펜던시 추가하니 이번엔 잘되더라고요.

 

 

 

JPA 를 사용해보면서 느낀점은 안드로이드하고 비교하면 ROOM 데이터베이스하고 좀 비슷한것 같습니다. ORM 을 지원해주며 JpaRepository <Entity>를 제네릭으로 상속받으면서 여러 SQL문도 자동으로 생성해주고 매우 편리한 것 같습니다.

다음과 같이 말이죠 find~ , save는 따로 레포지토리에서 만들지 않아도 있고요. save 같은 경우 알아서 ORM 으로 맵핑해서 저장해줍니다. 

JpaRepository에서 지원하지 않는 SQL 문은 @Query를 통해 직접 적어주면 되고요. 

public interface UserRepository extends JpaRepository<UserEntity, Long> {

    List<UserEntity> findUserEntityByEmail(String email);

    List<UserEntity> findUserEntityByName(String name);
}
@Transactional
    public Long saveUser(UserDto userDto) {
        return userRepository.save(userDto.toEntity()).getId();
    }

https://arahansa.github.io/docs_spring/jpa.html

 

스프링 데이터 JPA 레퍼런스 번역 문서입니다.

어플리케이션의 데이터 접근 레이어를 구현하는 것은 꽤 성가신 일이었습니다. 간단한 쿼리와, 페이징, auditing를 위해 너무 많은 보일러플레이트 코드가 쓰여져야했습니다. 스프링데이터JPA는 실제 필요한 부분에 대해서 많은 양의 노력을 줄이게 함으로써, 데이터 접근 레이어의 향상에 목표를 두고 있습니다. 개발자가 커스텀 찾기 메소드를 포함해 리파지토리 인터페이스를 작성하기만 하면, 스프링은 구현체를 자동적으로 제공할 것입니다.

arahansa.github.io

위 사이트에서 JPA 의 기능을더 자세히 알 수 있습니다.

 

 

 

일단 세팅내용은 다음과 같이했습니다. (일단은..)

 

[porm.xml 은 다음과 같습니다.]

springboot 관련 디펜던시(thymeleaf, web 등), lombok, 부스스트랩, mysql 등을 추가했습니다.

<?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.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mtjin</groupId>
    <artifactId>itarticle</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>itarticle</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--h2-->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

        <!-- BootStrap -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1</version>
        </dependency>
        <!-- DB(mysql) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>


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

</project>

 

 

 

 

[디렉토리 구조는 다음과 같습니다. ]

 

 

 

 

 

 

 

[Controller]

package com.mtjin.itarticle.controller;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@AllArgsConstructor
public class LoginController {
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView goLogin() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/login");
        return mv;
    }

    @RequestMapping(value = "/register", method = RequestMethod.GET)
    public ModelAndView goRegister() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/register");
        return mv;
    }

    @RequestMapping(value = "/forgot", method = RequestMethod.GET)
    public ModelAndView goForgot() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/forgot");
        return mv;
    }

    @RequestMapping(value = "/reset", method = RequestMethod.GET)
    public ModelAndView goReset() {

        ModelAndView mv = new ModelAndView();
        mv.setViewName("views/login/reset");
        return mv;
    }
}

 

 

 

 

[Entity]

package com.mtjin.itarticle.domain.entity;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class TimeEntity {
    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}
package com.mtjin.itarticle.domain.entity;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
@Table(name = "user")
public class UserEntity extends TimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 20, nullable = false)
    private String email;

    @Column(length = 20, nullable = false)
    private String password;

    @Builder
    public UserEntity(Long id, String email, String password) {
        this.id = id;
        this.email = email;
        this.password = password;
    }
}

 

 

 

[Repository]

package com.mtjin.itarticle.domain.repository;

import com.mtjin.itarticle.domain.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;


public interface UserRepository extends JpaRepository<UserEntity, Long> {
}

 

 

 

[Service]

package com.mtjin.itarticle.service;

import com.mtjin.itarticle.UserDto;
import com.mtjin.itarticle.domain.repository.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@AllArgsConstructor
@Service
public class UserService {
    private UserRepository userRepository;

    @Transactional
    public Long saveUser(UserDto userDto){
        return userRepository.save(userDto.toEntity()).getId();
    }
}

 

 

 

[UserDto]

package com.mtjin.itarticle;

import com.mtjin.itarticle.domain.entity.UserEntity;
import lombok.*;

import java.time.LocalDateTime;

@Getter
@Setter
@ToString
@NoArgsConstructor
public class UserDto {
    private long id;
    private String email;
    private String password;

    public UserEntity toEntity() {
        UserEntity boardEntity = UserEntity.builder()
                .id(id)
                .email(email)
                .password(password)
                .build();
        return boardEntity;
    }

    @Builder
    public UserDto(long id, String email, String password, LocalDateTime createdDate, LocalDateTime modifiedDate) {
        this.id = id;
        this.email = email;
        this.password = password;
    }
}

 

 

 

 

 

스프링부트는 밑 블로그에서 많이 참고하고 있습니다. 설명이 자세하더라고요. 

https://victorydntmd.tistory.com/326?category=764331

 

[SpringBoot] 게시판 (2) - 게시글 추가하기

Springboot로 디자인이 하나도 없고 매우 간단한 게시판을 구현하는 시리즈입니다. 최종 소스는 깃헙에서 확인하실 수 있습니다. [SpringBoot] 게시판 (1) - 준비작업 [SpringBoot] 게시판 (2) - 게시글 추가하기..

victorydntmd.tistory.com

 

 

감사합니다. !!

728x90
Comments