Merge pull request 'feat : 샘플 코드작성 & 상세 주석' (#5) from kurt/kurt into dev

Reviewed-on: http://211.119.124.110:3000/cjm/clean-parking/pulls/5
pull/6/head
cjm 2 months ago
commit 5433d0cd21

@ -33,6 +33,16 @@ public class SampleController {
// GetMapping 안에 있는 Url을 요청하면 해당 컨트롤러 매소드(함수)로 들어온다
// 이걸 [엔드포인트]라고 한다.
//자바파일은 클래스와 매서드(함수)들로 이루어지는데 아래 링크를 한번 읽고오면 이해가 빠르다.
//첨부한 링크들에서 이해가 안가는 부분있으면 정민 호출하면 최대한 쉽게 풀어 설명해주려고 노력한다.
//추가로 변수나 매서드명을 만들때 축약어는 지양한다. 길어도 상관없다.
//누가 읽어도 무슨동작을 하는지 예측되도록 정의하는것이 좋다.
// ex) 좋은예 : samplePageReturn / 나쁜예 : smplPgRtrn
// ex) 좋은예 : findCpMainByMmcode / 나쁜예 : srchCm
//줄인다고 성능이 빨라지는것도 아니며 길이 제한이 있는것도 아니다.
//남이 읽기 좋은 코드를 만든다고 생각하고 만들어야 한다.
//https://velog.io/@luna001631/%EC%9E%90%EB%B0%94JAVA-%EB%A9%94%EC%86%8C%EB%93%9Cmethod%EB%9E%80
@GetMapping("/minwon/init/sample.do")
public String samplePageReturn() {
// .do로 리턴하는건 jsp페이지를 찾아서 리턴하라는 표시이다
@ -48,14 +58,29 @@ public class SampleController {
// 받아서 비즈니스에 맞춰 로직을 짜면 된다.
// 아래를 보면 위와 다르게 GetMapping 이 아니라 PostMapping이다.
// https://dev-coco.tistory.com/60 아래 블로그를 참고
@PostMapping("/minwon/init/sample-search.ajax")
@PostMapping("/minwon/init/sample-search-myBatis.ajax")
public ResponseEntity<?> sampleAjaxMybatis(@RequestBody SampleDto.Request.Search testDto) {
// Dto란
// https://people-analysis.tistory.com/269
// 프론트에서 바디로 넘어온 데이터를 @RequestBody를 통해 맵핑한다. 키값이 맞아야 벨류를 가져온다.
List<SampleDto.Response.cpMain> result = sampleService.searchSample(testDto);
List<SampleDto.Response.cpMain> result = sampleService.searchSampleMybatis(testDto);
return ResponseEntity.ok(result);
}
@PostMapping("/minwon/init/sample-search-JPA.ajax")
public ResponseEntity<?> sampleAjaxJPA(@RequestBody SampleDto.Request.Search testDto) {
// jpa도 똑같다.
// db호출을 마이바티스로 할것이냐 Jpa로 할것이냐 차이다.
// 마이바티스는 매퍼인터페이스와 매퍼xml을 통해 만들어야 하는 반면
// jpa는 자바로 모두 해결이 된다. = ORM
// https://dbjh.tistory.com/77
// 자바로 해결가능한것의 장점은 1. 코드 작성시 오타와 자동완성을 지원한다. 2.컴파일에러는 개발시 미리 알수있다. 3.재사용성이 뛰어나다. 정도가 있다.
// 1번만 되어도 생상성이 확 올라가서 결국 최종적으로는 jpa사용을 지향하는것이 좋아보인다.
List<SampleDto.Response.cpMain> result = sampleService.searchSampleJPA(testDto);
return ResponseEntity.ok(result);
}

@ -27,9 +27,9 @@ public class SampleDto {
public static class cpMain {
private String mmCode;
private String mmState;
private String mmCarNo;
private String mmKeum1;
private String mmKeum2;
private String mmCarno;
private Integer mmKeum1;
private Integer mmKeum2;
private String mmDate;
private String mmTime;
}

@ -0,0 +1,45 @@
package go.kr.project.biz.minwon.init.repository;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import go.kr.project.biz.minwon.init.model.MinwonInitDto;
import go.kr.project.biz.minwon.init.model.SampleDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import java.util.List;
import static go.kr.project.domain.entity.QCpMain.cpMain;
@Repository
@RequiredArgsConstructor
public class SampleQueryDslRepository {
private final JPAQueryFactory queryFactory;
public List<SampleDto.Response.cpMain> findSample(SampleDto.Request.Search testDto) {
List<SampleDto.Response.cpMain> result = queryFactory
.select(
Projections.fields(
SampleDto.Response.cpMain.class,
//만약 컬럼과 바인딩할 객체의 명이 다르다면 as로 dto에 맞추면 된다.
cpMain.mmCode.as("mmCode"),
cpMain.mmState,
cpMain.mmCarno,
cpMain.mmKeum1,
cpMain.mmKeum2,
cpMain.mmDate,
cpMain.mmTime
)
)
.from(cpMain)
.where(
cpMain.mmState.eq(testDto.getMmState())
)
.fetch();
return result;
}
}

@ -12,5 +12,7 @@ public interface SampleService {
//이 인터페이스에 정의한 매소드는 반드시 impl로 구현해야함.
//조회
List<SampleDto.Response.cpMain> searchSample(SampleDto.Request.Search testDto);
List<SampleDto.Response.cpMain> searchSampleMybatis(SampleDto.Request.Search testDto);
List<SampleDto.Response.cpMain> searchSampleJPA(SampleDto.Request.Search testDto);
}

@ -2,12 +2,17 @@ package go.kr.project.biz.minwon.init.service.impl;
import go.kr.project.biz.minwon.init.mapper.SampleMapper;
import go.kr.project.biz.minwon.init.model.SampleDto;
import go.kr.project.biz.minwon.init.repository.SampleQueryDslRepository;
import go.kr.project.biz.minwon.init.service.SampleService;
import go.kr.project.domain.entity.CpMain;
import go.kr.project.domain.repo.cp.CpMainRepository;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
//아까 어쩔수 없이 넣은 인터페이스의 구현체이다.
//컨트롤러에서 인터페이스를 호출하면 이게 실행되는것이다.
@ -20,13 +25,60 @@ public class SampleServiceImpl extends EgovAbstractServiceImpl implements Sample
//dao : DataBase Access Object로 디비와 연겷하는 역할은 한다.
// 현재 프로젝트에서는 dao역할은 mybatis 매퍼인터페이스로 한다.
private final SampleMapper sampleMapper;
//Jpa 레파지토리 주입 (선택)
//Jpa를 통한 조회를 할때 주입해줘야한다.
private final CpMainRepository cpMainRepository;
//QueryDsl을 사용할때 주입한다.(선택)
private final SampleQueryDslRepository sampleQueryDslRepository;
@Override
public List<SampleDto.Response.cpMain> searchSample(SampleDto.Request.Search testDto) {
public List<SampleDto.Response.cpMain> searchSampleMybatis(SampleDto.Request.Search testDto) {
// 매퍼 xml의 resultType을 리턴값으로 받아야한다.
List<SampleDto.Response.cpMain> result = sampleMapper.selectAllSample(testDto);
return result;
}
@Override
//매소드에 대한 트렌젝션을 해주는 어노테이션.
@Transactional
public List<SampleDto.Response.cpMain> searchSampleJPA(SampleDto.Request.Search testDto) {
//Jpa 레파지토리를 통한 조회
//Jpa 레파지토리의 경우 조회한 결과가 엔티티 객체임. dto와는 다른객체임.
//그래서 엔티티로 조회해 왔으면 dto로 변환하는 과정이 필요함.
//간단하면 스트림(stream) 빌더(builder)를 많이 씀.
//1.Jpa 레파지토리 방식
//간단한 조회(단일)의 경우를 많이씀.
//조인이 필요한경우 Jpql로 인터페이스에 작성을 해야하는데 컨트롤러에서 설명한 1번의 장정이 사라짐.
//그래서 대안책으로 나온 라이브러리가 2.QueryDsl임.
List<CpMain> jpaResult = cpMainRepository.findByMmState(testDto.getMmState());
List<SampleDto.Response.cpMain> convertEntityToDtoResult = jpaResult.stream()
.map(entity -> {
SampleDto.Response.cpMain dto = new SampleDto.Response.cpMain();
dto.setMmCode(entity.getMmCode());
dto.setMmState(entity.getMmState());
dto.setMmCarno(entity.getMmCarno());
dto.setMmKeum1(entity.getMmKeum1());
dto.setMmKeum2(entity.getMmKeum2());
dto.setMmDate(entity.getMmDate());
dto.setMmTime(entity.getMmTime());
return dto;
})
.collect(Collectors.toList());
//2. QueryDsl방식
//복잡한 조인, 벌크인서트, 벌크업데이트등을 쉽게 할수 있음.
//장점은 Jpa레파지토리의 내장매서드를 알 필요 없이 기존 쿼리문과 비슷한 형태로 쓸수 있음.
//1. 번의 단순한 조회일 경우도 QueryDsl을 써도 무방함.
List<SampleDto.Response.cpMain> queryDslResult = sampleQueryDslRepository.findSample(testDto);
//리턴은 주석을 바꿔가며 테스트 해볼수 있다.
// return convertEntityToDtoResult;
return queryDslResult;
}
}

@ -4,8 +4,13 @@ import go.kr.project.domain.entity.CpMain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CpMainRepository extends JpaRepository<CpMain,String> {
CpMain findTopByMmCodeStartingWithOrderByMmCodeDesc(String prefix);
List<CpMain> findByMmState(String mmState);
}

@ -10,7 +10,16 @@
</br></br></br>
<input type="button" value="샘플 버튼">
<input type="button" id="mybatis-call" value="샘플 myBatis 호출 버튼">
</br>
<input type="button" id="jpa-call" value="샘플 Jpa 호출 버튼">
</br>
<input type="button" id="clear" value="조회결과 클리어">
<div>
<pre id="result"></pre>
</div>
</br></br></br></br>
<select>
<option value="aaa">aaa</option>
@ -47,19 +56,66 @@
search: () => {
//아작스는 비동기 서버호출 함수이다. 아래 블로그 설명글 참고
//https://jbground.tistory.com/4
$.ajax({
url: "",
type: "POST",
data: { id : "" },
success: function(response) {
},
error: function(xhr, status, error) {
}
// $.ajax({
// url: "/minwon/init/sample-search.ajax",
// type: "POST",
// contentType: 'application/json',
// data: JSON.stringify({ "id" : "" }),
// success: function(response) {
//
// },
// error: function(xhr, status, error) {
//
// }
// });
},
eventListener: () => {
$("#mybatis-call").on("click", () => {
//아작스는 비동기 서버호출 함수이다. 아래 블로그 설명글 참고
//https://jbground.tistory.com/4
$.ajax({
url: "/minwon/init/sample-search-myBatis.ajax",
type: "POST",
contentType: 'application/json',
data: JSON.stringify({ mmState : "01" }),
success: function(response) {
$("#result").text("");
$("#result").text(JSON.stringify(response, null, 2));
},
error: function(xhr, status, error) {
$("#result").text("조회 실패");
}
});
});
$("#jpa-call").on("click", () => {
console.log("aaa")
$.ajax({
url: "/minwon/init/sample-search-JPA.ajax",
type: "POST",
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({ mmState : "01" }),
success: function(response) {
$("#result").text("");
// $("#result").text(response);
$("#result").text(JSON.stringify(response, null, 2));
},
error: function(xhr, status, error) {
$("#result").text("조회 실패");
}
});
});
$("#clear").on("click", () => {
$("#result").text("");
})
}
}
@ -74,6 +130,7 @@
// 예를들어 페이지 진입하면서 바로 조회를 하게 만들고 싶다면, 에제와 같이 init함수 안에 조회하는 함수호출해버리면 된다.
// 안에 로직을 나열해도 상관없지만, 추후 유지보수를 위해 함수를 기능별로 묶어 함수호출을 통한 플로우 개발을 지향한다.
$(function () {
fnBiz.eventListener();
fnBiz.init();
});

Loading…
Cancel
Save