JDBC

  • JDBC는 DB에 접근하고, SQL을 날릴 수 있게 해주는 자바의 표준 API
  • DriverMAnager를 사용해 각 드라이버들을 로딩, 해제한다.

[출처] https://skyblue300a.tistory.com/7

JPA

  • JPA는 자바 진영 ORM의 API 표준 명세
  • 내부적으로 JDBC를 사용

[출처] https://skyblue300a.tistory.com/7

Spring JDBC(SQL Mapper → MyBatis)

  • JDBC에서 DriveManager가 하는 일들을 JdbcTemplate에게
  • 쿼리문을 사용한다.

[출처] https://skyblue300a.tistory.com/7

Spring Data JDBC

  • Spring data는 Spring에서 DB를 쉽게 다루기 위해 시작한 프로젝트
  • @Query 어노테이션 사용

[출처] https://skyblue300a.tistory.com/7

Hibernate

  • JPA를 구현한 프레임워크
  • Spring은 기본 JPA vendor로 Hibernate를 사용

[출처] https://skyblue300a.tistory.com/7

정리

 

 

❗ 나는 Hibernate를 사용해 구현할 예정..!!!! ❗

'Web > Spring' 카테고리의 다른 글

[Annotation] @PathVariable  (0) 2021.08.06
[Pageable] 페이징 처리 - 기본  (0) 2021.08.06
[설정] 자동망치 기능  (0) 2021.08.06
[설정] application.properties  (0) 2021.08.04
[CRUD] R구현  (0) 2021.08.02

자동망치 기능

  • view쪽을 수정하고 재실행하지 않고 망치를 눌러서 수정된 화면을 확인할 수 있다.(ctrl+shift+r)

intelliJ 위쪽 메뉴바

초록색 망치모양을 클릭한 후 화면에서 ctrl+shift+r을 눌러 새로고침한다.

 

자동망치 설정

  • 의존성 추가
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
      <optional>true</optional>
    </dependency>

 

  • properties 설정
 <!--- application.yml--->
    devtools:
      livereload:
        enabled: false
      add-properties: false
      restart:
        enabled: false
        
<!--- application-local.yml--->
    devtools:
      livereload:
        enabled: true
      add-properties: true
      restart:
        enabled: false

 

  • Edit Configuration

초록 망치 옆 네모칸 클릭

Active profiles를 local로 설정해준다

'Web > Spring' 카테고리의 다른 글

[Pageable] 페이징 처리 - 기본  (0) 2021.08.06
[배경] JPA vs JDBC, JPA vs Mybatis, JPA vs Spring Data JPA  (0) 2021.08.06
[설정] application.properties  (0) 2021.08.04
[CRUD] R구현  (0) 2021.08.02
[CRUD] C구현  (0) 2021.08.02

properties 파일

  • Spring에서 서비스에 필요한 설정 정보 등을 텍스트 파일 형태로 관리하기 위한 설정 파일(외부 설정 파일)
  • Spring boot가 App을 구동할 때 자동으로 로딩하게 해 준다
  • properties 말고 YAML파일도 있음(application.properties → application.yml)
  • 우선순위
    • 유저 홈 디렉터리에 있는 spring-boot-dev-tools.properties
    • 테스트에 있는 @TestPropertySource
    • @SpringBootTest annotation의 properties attribute
    • command line argument
    • SPRING_APPLICATION_JSON에 들어있는 property
    • ServletConfig 파라미터
    • ServletContext 파라미터
    • ... https://100100e.tistory.com/378 (참고)

 

Profile에 따른 환경 구성 분리

DB의 경우 로컬(local), 개발(dev), 운영에 따라 각각의 설정값이 모두 다를 수 있다!

YAML파일의 경우 --- 을 사용해 나누거나 파일을 복사해 이름을 변경해 사용.

--- 으로 구분
이름으로 구분

properties 또한 필요에 의해 나눠준다.

이름으로 구분

이를 IntelliJ에서 실행할 때 Edit Configurations 메뉴를 클릭하고 Run/Debug Configurations 창에서 Active Profiles 값을 설정해주고 실행

 

❗ 주로 local에서 실행할듯...? 자동망치는 local이랑 yaml 파일 설정 고치면 가능하다.. 이는 좀 이따가.. ❗

'Web > Spring' 카테고리의 다른 글

[배경] JPA vs JDBC, JPA vs Mybatis, JPA vs Spring Data JPA  (0) 2021.08.06
[설정] 자동망치 기능  (0) 2021.08.06
[CRUD] R구현  (0) 2021.08.02
[CRUD] C구현  (0) 2021.08.02
[JPA] 데이터베이스 생성 또는 초기화  (0) 2021.08.02

fontawesome 아이콘 삽입

https://fontawesome.com/

 

Font Awesome

The world’s most popular and easiest to use icon set just got an upgrade. More icons. More styles. More Options.

fontawesome.com

위의 사이트에서 원하는 아이콘을 찾는다! (pro 붙어있는 것은 유료이다)

 

HTML파일 안에 script 추가

<!DOCTYPE html>
<html>
  <head>
    <script src="https://use.fontawesome.com/releases/v5.2.0/js/all.js"></script>
  </head>
  <body></body>
</html>

 

사이트에서 원하는 아이콘을 찾으면 <i>태그를 복사한 후 HTML파일에 붙여 넣는다.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://use.fontawesome.com/releases/v5.2.0/js/all.js"></script>
  </head>
  <body>
    <div style="font-size: 30px;">
      <i class="fas fa-smile"></i>
    </div>
  </body>
</html>

'Web > Front' 카테고리의 다른 글

[HTML] 템플릿 파일 적용 규칙  (0) 2021.07.30
[Javascript] window.location 객체  (0) 2021.07.30
[HTML] HTML 템플릿 다운로드 사이트  (0) 2021.07.30
[ERROR] 500에러 관련  (0) 2021.07.30
[ERROR] static파일 적용 관련  (0) 2021.07.30

CRUD

  • Create (INSERT)
  • Read (SELECT)
  • Update (UPDATE)
  • Delete (DELETE)

Read 구현

필요한 것

  • DB table에서 원하는 내용을 꺼내올 것
  • list 화면에 내용들을 list로 보여줌
  • list들 중 하나를 클릭하면 read화면이 떠서 볼 수 있게

 

❗ C구현에서 했던 filter와 service, repository들을 그대로 활용할 예정 ❗

먼저 list화면을 구현

<!DOCTYPE HTML>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<head>
  <th:block th:replace="fragments/head :: head"></th:block>
  <link rel="stylesheet" th:href="@{/static/assets/css/project-list.css}" type="text/css"/>
  <style>
    h2, p {
      font-weight: bold;
    }
    a {
      text-decoration: none;
      color: #777777;
    }
  </style>
</head>

<body class="is-preload">
<div id="wrapper">
  <th:block th:replace="fragments/top :: top"></th:block>
  <div id="main">
    <article id="work" class="panel">
      <header>
        <h2>Project</h2>
      </header>
      <p>
        A field of interest :
        <span style="font-weight: lighter">Cloud(AWS, OpenStack), WEB(Spring), DevOps</span>
      </p>

      <table class="type09">
        <thead>
        <tr>
          <th scope="col">No.</th>
          <th scope="col">Progress Date</th>
          <th scope="col">Project Title</th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="p: ${projectList}">
          <td scope="row" style="width: 50px"><a th:text="${p.id}" th:href="|@{/project/read}/${p.id}|"></a> </td>
          <td><a th:text="${p.date}" th:href="|@{/project/read}/${p.id}|"></a> </td>
          <td><a th:text="${p.title}" th:href="|@{/project/read}/${p.id}|"></a> </td>
        </tr>
        </tbody>
      </table>
      <a class="addButton" th:text="|ADD|" th:href="|@{/project/edit}|"></a>
    </article>
  </div>
</div>
<th:block th:replace="fragments/footer :: footer"></th:block>
<th:block th:replace="fragments/common-script :: common-script"/>
</body>
</html>

 

읽을 read화면도 구현

<!DOCTYPE HTML>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<head>
  <th:block th:replace="fragments/head :: head"></th:block>
  <link rel="stylesheet" th:href="@{/static/assets/css/project-read.css}" type="text/css"/>
  <style>
    h2 {
      font-weight: bold;
    }
  </style>
</head>

<body class="is-preload">
<div id="wrapper">

  <th:block th:replace="fragments/top :: top"></th:block>
  <div id="main">
    <article id="work" class="panel" th:object="${project}">
      <h2>Project</h2>
      <div class="mb-3">
        <h4 class="title" th:text="*{title}"></h4>
      </div>
      <div class="mb-3">
        <h5 class="date" th:text="*{date}"></h5>
      </div>
      <hr class="one">
      <div class="mb-3">
        <h5 class="purpose" th:text="*{purpose}"></h5>
      </div>
      <hr class="two">
      <div class="mb-3">
        <h5 class="technology" th:text="*{technology}"></h5>
      </div>
      <hr class="two">
      <div class="mb-3">
        <h5 class="address" th:text="*{address}"></h5>
      </div>

    </article>
  </div>
</div>
<th:block th:replace="fragments/footer :: footer"></th:block>
<th:block th:replace="fragments/common-script :: common-script"/>
</body>
</html>

 

이 화면들을 띄워줄 controller 구현

@Controller
@RequiredArgsConstructor
@RequestMapping("/project")
public class ProjectController {

 @NonNull
  private final ProjectService projectService;

  @GetMapping("")
  public String list(Model model, Pageable pageable, ProjectFilter filter) {

    model.addAttribute("projectList", projectService.findAllByFilter(pageable, filter));
    model.addAttribute("filter", filter);
    return "project/list";
  }
  
   @GetMapping("/read/{id}")
  public String read(@PathVariable Integer id, Model model) {

    Project project = projectService.findById(id).orElseThrow(DataNotFoundException::new);
    model.addAttribute("project",project);

    return "project/read";
  }
}

여기까지 구현하면 CR구현이 완성되었다!

list 화면
read 화면

 

❗ 코드 관련 문법이나 필요한 내용들은 따로 정리할 예정이며 UD는 천천히 구현해볼 예정이다! ❗

'Web > Spring' 카테고리의 다른 글

[설정] 자동망치 기능  (0) 2021.08.06
[설정] application.properties  (0) 2021.08.04
[CRUD] C구현  (0) 2021.08.02
[JPA] 데이터베이스 생성 또는 초기화  (0) 2021.08.02
[ERROR] Pageable import  (0) 2021.08.02

CRUD

  • Create (INSERT)
  • Read (SELECT)
  • Update (UPDATE)
  • Delete (DELETE)

 

Create 구현

필요한 것

  • DB 테이블 생성(Domain → maven compile)
  • 필요한 정보를 가져다 줄 filter
  • View와 Controller(edit화면과 해당 뷰를 띄워줄 controller)
  • view와 controller를 연결할 repository, service

/java/com.OOOO/domain 폴더 아래에 본인이 만들고 싶은 domain 생성

❗ 나는 Project 도메인을 기준으로 잡았다. ❗

@Getter
@Setter
@Entity
@Table(name = "project", indexes = {})
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Project {
  //기본정보
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @EqualsAndHashCode.Include
  private Integer id;

  @JsonIgnore
  @DateTimeFormat(pattern = DateUtil.PATTERN_YMDHMS)
  @Column(nullable = false, insertable = false, updatable = false, columnDefinition = "timestamp(6) default current_timestamp(6)")
  private LocalDateTime createDate;   //생성일시

  @JsonIgnore
  @DateTimeFormat(pattern = DateUtil.PATTERN_YMDHMS)
  @Column(nullable = false, insertable = false, updatable = false, columnDefinition = "timestamp(6) default current_timestamp(6) on update current_timestamp(6)")
  private LocalDateTime updateDate;   //변경일시

  //추가정보
  @Column(nullable = false, length = 255)
  private String date; //프로젝트 진행날짜

  @Column(nullable = false)
  private String title; // 프로젝트 제목

  private String purpose; // 프로젝트 목적

  private String technology; // 프로젝트 사용기술

  private String address; // 프로젝트 깃헙주소

}

 

DB table에서 가져올 내용들을 filter로 가져온다. (/java/com.OOOO/filter)

❗ 나중에 filter를 통해 pageable 사용할 예정 ❗

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ProjectFilter {

  private String title;
  private String date;
  private String purpose;
  private String technology;
  private String address;
}

 

View 화면 생성(/resources/templates)

❗ 아래 코드는 현재 내가 진행하고 있는 프로젝트 코드이므로 그냥 바로 적용하면 깨질 것임. 따라서 알맞게 맞춰서 바꾸어줘야 함! ❗

<!DOCTYPE HTML>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<head>
  <th:block th:replace="fragments/head :: head"></th:block>
  <link rel="stylesheet" th:href="@{/static/assets/css/project-edit.css}" type="text/css"/>
  <style>
    h2 {
      font-weight: bold;
      margin-bottom: 20px;
    }
  </style>
</head>

<body class="is-preload">
<div id="wrapper">
  <th:block th:replace="fragments/top :: top"></th:block>
  <div id="main">
    <article id="work" class="panel">
      <h2>Project ADD</h2>
      <form method="post"
            th:action="|@{/project/save}|" th:object="${project}">
        <input th:field="*{id}" type="hidden"/>
        <button class="saveButton" type="submit" th:text="|save|"></button>
        <div class="mb-3">
          <label class="form-label" for="date">Progress Date</label>
          <input type="text" class="form-control" name="date" id="date" th:field="*{date}"
                 placeholder="프로젝트 진행 날짜를 입력해 주세요">
        </div>
        <div class="mb-3">
          <label class="form-label" for="title">Project Title</label>
          <input type="text" class="form-control" name="title" id="title" th:field="*{title}"
                 placeholder="프로젝트 제목을 입력해 주세요">
        </div>
        <div class="mb-3">
          <label class="form-label" for="purpose">Project Purpose</label>
          <input type="text" class="form-control" name="purpose" id="purpose" th:field="*{purpose}"
                 placeholder="프로젝트 목적을 입력해 주세요">
        </div>
        <div class="mb-3">
          <label class="form-label" for="content">Used Technology</label>
          <textarea class="form-control" rows="5" name="content" id="content"
                    th:field="*{technology}"
                    placeholder="사용한 기술을 입력해 주세요"></textarea>
        </div>
        <div class="mb-3">
          <label class="form-label" for="address">Github Address</label>
          <input type="text" class="form-control" name="address" id="address" th:field="*{address}"
                 placeholder="Github 주소를 입력해 주세요">
        </div>
      </form>
    </article>
  </div>
</div>
<th:block th:replace="fragments/footer :: footer"></th:block>
<th:block th:replace="fragments/common-script :: common-script"/>
</body>
</html>

 

이제 view와 연결 지을 controller 구현(/java/com.OOOO/controller)

❗ edit화면을 띄울 것과 적은 내용을 save 해서 DB에 저장이 되어야 함 ❗

@Controller
@RequiredArgsConstructor
@RequestMapping("/project")
public class ProjectController {

 @NonNull
  private final ProjectService projectService;
  
   @GetMapping({"/edit", "/edit/{id}"})
  public String edit(@PathVariable(required = false) Integer id, Model model) {

    Project project = (id == null) ? new Project() : projectService.findById(id).orElseThrow(
        DataNotFoundException::new);

    model.addAttribute("project", project);

    return "project/edit";
  }
  
   @PostMapping("/save")
  public String save(@ModelAttribute("project") Project project, BindingResult result, Model model,
      RedirectAttributes redirectAttr) {

    if (!result.hasErrors()) {
      projectService.save(project);
      redirectAttr.addFlashAttribute("message", "저장되었습니다.");
      return "redirect:/project/edit/" + project.getId();
    }
    model.addAttribute("project", project);
    return "project/edit";
  }
  
}

 

controller 안에 써있는 함수들을 구현해줘야 함!

제일 먼저 Repository 생성(/java/com.OOOO/repository)

@Repository
public interface ProjectRepository extends JpaRepository<Project, Integer>,
    CustomProjectRepository {
}

다음으론 customRepository 생성(/java/com.OOOO/repository/custom)

❗ findAllByFilter : filter를 통해 페이지를 구성할 계획 / 이것은 list를 뽑아낼 때 필요한 것 ❗

@NoRepositoryBean
public interface CustomProjectRepository {

  Page<Project> findAllByFilter(Pageable pageable, ProjectFilter filter);

}

마지막으론 RepositoryImpl 생성(/java/com.OOOO/repository/support)

❗ querydsl사용으로 코드로 db 코드를 만질 수 있다! ❗

public class ProjectRepositoryImpl extends QuerydslRepositorySupport implements
    CustomProjectRepository {

  private final QProject project = QProject.project;

  public ProjectRepositoryImpl() { super(Project.class); }

  @Override
  public Page<Project> findAllByFilter(Pageable pageable, ProjectFilter filter) {
    BooleanBuilder builder = new BooleanBuilder();

    if (!StringUtils.isBlank(filter.getDate())) {
      builder.and(project.date.containsIgnoreCase(filter.getDate()));
    }
    if (!StringUtils.isBlank(filter.getTitle())) {
      builder.and(project.title.containsIgnoreCase(filter.getTitle()));
    }
    if(!StringUtils.isBlank(filter.getAddress())){
      builder.and(project.address.containsIgnoreCase(filter.getAddress()));
    }
    if(!StringUtils.isBlank(filter.getTechnology())){
      builder.and(project.technology.containsIgnoreCase(filter.getTechnology()));
    }
    if(!StringUtils.isBlank(filter.getAddress())){
      builder.and(project.purpose.containsIgnoreCase(filter.getPurpose()));
    }

    final JPQLQuery<Project> query = from(project).where(builder);

    List<Project> result = getQuerydsl().applyPagination(pageable, query).fetch();

    return new PageImpl<>(result,pageable,query.fetchCount());

  }

}

 

repository 구성이 끝났다면 이를 controller에 가져다 사용할 수 있게 service를 구현(/java/com.OOOO/repository/service)

@Service
@RequiredArgsConstructor
public class ProjectService {

  @NonNull
  private final ProjectRepository projectRepository;

  public Optional<Project> findById(Integer id) { return projectRepository.findById(id); }

  public Page<Project> findAllByFilter(Pageable pageable, ProjectFilter filter) {
    return projectRepository.findAllByFilter(pageable, filter);
  }

  public Project save(Project project) {
    return projectRepository.save(project);
  }
}

 

현재까지 진행하면 나오는 결과

edit 화면

save 버튼을 누르면

DB 결과

DB에 저장이 됨을 확인할 수 있다.

 

 

❗ 혼자 진행 중인 프로젝트를 가져온 거라 아마 본인에 맞게 고쳐야 할 부분이 많을 것이다! 그래도 저 순서대로 하면 글 작성과 저장까지는 구현하는데 도움이 될지도...? 다음 포스팅은 R에 관해 구현할 예정 ❗

'Web > Spring' 카테고리의 다른 글

[설정] application.properties  (0) 2021.08.04
[CRUD] R구현  (0) 2021.08.02
[JPA] 데이터베이스 생성 또는 초기화  (0) 2021.08.02
[ERROR] Pageable import  (0) 2021.08.02
[ERROR] Querydsl import  (0) 2021.08.02

+ Recent posts