프로그래밍

[웹 프로그래밍] 스프링부트JPA 8. 테이블을 자동생성해보자~.

tt2t2am1118 2023. 1. 14. 06:50
반응형

 

이번편은 테이블 자동생성입니다.

 

전편에서 엔티티를 자동생성은 해봤었는데요. Repository, Service역시 자동으로 만들어주죠.

 

중복코드가 많기에... 제 생각엔 한 80~90%는 중복코드 같습니다. 물론, 테이블이 맵핑. 여러테이블로 구성되어있다면, 편집은 해야하죠.

 

https://github.com/infott2t/SpringAutoCodeJPAEntity3

 

GitHub - infott2t/SpringAutoCodeJPAEntity3: Automation Code CRUD. SpringBoot JPA + QueryDSL

Automation Code CRUD. SpringBoot JPA + QueryDSL . Contribute to infott2t/SpringAutoCodeJPAEntity3 development by creating an account on GitHub.

github.com

 

위의 github을 인텔리제이에, 설치해줌니다. 제가 만든 프로젝트이군요. 

 

전에 엔티티, Repository, Service 클래스의 자동생성은 이 편을 참조해보세요.

[웹 프로그래밍] 스프링부트JPA 1. 데이터를 클래스화 하기. 자동 생성. (tistory.com)

 

[웹 프로그래밍] 스프링부트JPA 1. 데이터를 클래스화 하기. 자동 생성.

공부해봅시다. 오늘은 클래스 형식으로 데이터 만들어보기 입니다. 스프링부트를 통해서, 엔티티클래스를 만들면, 자동화를 통해 프로그래밍을 더 쉽게 할 수 있습니다. 백엔드와 프론트엔드로

tt2t2am.tistory.com

 

이번 편은, CRUD의 url. insert, list출력, update, delete... 이런 로직, html들을 자동생성해주는 것이군요~.

@Entity
public class PhoneStr extends BaseTimeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PHONE_STR_ID")
    private Long id;

    //전화번호
    private String phoneNumber;
    
    private String isDel;
    private LocalDateTime modifiedDate;
    private LocalDateTime createdDate;
    
    }

전화번호를 저장하는 엔티티를 예를 들게요.  맨위에는  Long id. 그리고, isDel과 modifiedDate, createDate는 그대로 사용해줘야하고, modefiedDate, createDate는 안적어야 하는 군요.

위 처럼 적고, Extract Redundant.. 버튼을 누르면 파일이 생성됨니다. c:\category에 생성이 되요. 그 파일들을 프로젝트에 붙이면 됨니다. 패키지는 적혀있지 않으니, 적어주시구요.

 

엔티티를 생성할 때에, isDel, modifiedDate, createdDate. 이 세개의 변수를 잘 적어두어야, 위 처럼 코드생성기를 잘 이용할 수 있습니다.

 

 

또, 메소드. 이부분은 따로 생성해줘야합니다. Service클래스에 맞춰서 적어주면됨니다.

    @Transactional(readOnly = true)
    public Page<AddressStrApiDto> searchAllV2(AddressStrSearchCondition condition, Pageable pageable) {
        return addressStrRepository.searchAllV2(condition, pageable);
    }

파일들을 경로에 맞게 저장한 뒤 실행...

index.html에 링크 경로를 지정해주구요~.

resource/templates/index.html.

     <p><a th:href="@{/administer/instanceurl/phoneStr}">phone 게시판 엔티티 PhoneStr 로 이동</a> </p>

 

또, Impl파일. QueryDsl검색할 때에, where절을 추가해줌니다. 페이징할 때에 isDel이 N인 것... 지우지 않은 것만 나오게 해줘야하죠.

 

PhoneStrRepositoryImpl클래스,

@Override
    public Page<PhoneStrApiDto> searchAllV2(PhoneStrSearchCondition condition, Pageable pageable) {

        List<PhoneStrApiDto> content = queryFactory.
                select(Projections.constructor(PhoneStrApiDto.class,
                        phoneStr.id,
                        phoneStr.phoneNumber,
                        phoneStr.isDel,
                        phoneStr.modifiedDate,
                        phoneStr.createdDate
                )).from(phoneStr)
                .where(
                        searchAllV2Predicate(condition)
                ).where(phoneStr.isDel.eq("N"))
                .orderBy(phoneStr.id.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

        long total = queryFactory
                .select(phoneStr.count())
                .from(phoneStr)
                .where(
                        searchAllV2Predicate(condition)
                ).where(phoneStr.isDel.eq("N"))
                .fetch().get(0);

        return new PageImpl<>(content, pageable, total);
    }

QueryDsl의 검색기능을 사용하려면, 주석을 풀어주고... 이런 식으로 적어주면 됨니다. 검색할 것이 어떤것이 되는지 생각해보면 되겠습니다. 위의 엔티티의 경우에는, phoneNumber가 되겠죠~.

 

hasText의 import도 필요합니다.

import static org.springframework.util.StringUtils.hasText;
    private BooleanBuilder searchAllV2Predicate(PhoneStrSearchCondition condition){
        return new BooleanBuilder()
                .and(condS(condition.getField(), condition.getS()))
                .and(condSdate(condition.getSdate()))
                .and(condEdate(condition.getEdate()));

    }

    private Predicate condS(String field, String s){
        BooleanBuilder builder = new BooleanBuilder();

        if(hasText(field) && hasText(s)) {
            if(field.equals("phoneNumber")) {

                builder.or(phoneStr.phoneNumber.like("%" + s + "%"));
               
                

            }  
        }

        return builder;
    }

    private Predicate condSdate( String sdate){
        BooleanBuilder builder = new BooleanBuilder();

        if(hasText(sdate)){
            try {
                LocalDateTime localDateTime = LocalDateTime.parse(sdate + "T00:00:00");
                builder.or(phoneStr.modifiedDate.goe(localDateTime)); // isrtDate >= sdate

            } catch (DateTimeParseException e) {
            }
        }
        return builder;
    }

    private Predicate condEdate( String edate){
        BooleanBuilder builder = new BooleanBuilder();
        if(hasText(edate)) {
            try {
                LocalDateTime localDateTime = LocalDateTime.parse(edate + "T00:00:00");
                builder.or(phoneStr.modifiedDate.loe(localDateTime)); // isrtDate <= edate

            } catch (DateTimeParseException e) {
            }
        }
        return builder;
    }

또, 엔티티에 맞게 검색조건을 바꿨다면.. html파일에 검색 필드 값도 추가해줘야겠죠~.

index, insert, update. 3개의 파일에서 검색조건부분을 변경해줌니다. 

 

<option th:value="id" th:selected="${#strings.trim(param.field) eq 'id'}">id</option>
<option th:value="phoneNumber" th:selected="${#strings.trim(param.field) eq 'phoneNumber'}">전화번호</option>

잘 되는 걸 볼 수 있습니다. 테이블 만들기가 수월해지겠군요.

 

처음 배우시는 분들은, 인터넷 강의 듣기 추천드려요~. QueryDSL.

 

중복코드가 치기 싫다... 이러신 분들이라던지, 현업에서 일하시는 분들이라든지... 도움이 되었으면 좋겠습니다. 

 

 빠르면, 5초.... 과장해서요. 한 5분정도 걸리는 것 같아요~. 원래 타이핑하려면... 3~4시간.. 혹은 하루의 시간이 걸리는 양이라고 생각해봄니다.

 

저도 제가 만들고 있는 코드... 이어서 만들어야죠~. 좋은 하루, 좋은 개발되세요.

 

--

저의 글, 봐 주셔서 감사합니다.

반응형