[토이 투표] 개발일지(엔티티 수정, update 수정, 특정 조인 검색 수정)

재호·2022년 6월 30일
0

엔티티 수정

수정 전
create table tbl_member(
	email varchar(255) not null, 
    password varchar(255) not null,
    name varchar(255),
    nickname varchar(255) unique,
    officialmark boolean,
    regdate datetime(6),
    moddate datetime(6),
    primary key(email)
)engine=InnoDB default charset=utf8;


수정 후
create table tbl_member(
	mno integer auto_increment,
	email varchar(255) not null unique, 
    password varchar(255) not null,
    name varchar(255),
    nickname varchar(255) unique,
    officialmark boolean,
    regdate datetime(6),
    moddate datetime(6),
    primary key(mno)
)engine=InnoDB default charset=utf8;

기존에는 사용자의 이메일을 기본키로 설정해놨었는데 앞으로 정부 규칙이나 특별한 이유로 기본키가 수정될 가능성이 조금이라도 있어서는 안되기에 자동 생성 번호로 기본키를 바꾸었다. tbl_member 테이블이 기본키를 수정하면서 board 테이블의 외래키 또한 수정하였다.

Update 메서드 수정

기존에는 JPARepository 인터페이스의 공용 메서드인 save를 사용해서 수정하였는데, save의 동작원리는 매개변수로 받은 엔티티의 기존 존재여부를 확인하고 없다면 persist를 하지만 만약 기존에 있던 엔티티라면 merge를 하게된다. merge는 무조건 select 쿼리가 한번 날아가게 되므로 성능면에서 효율적이지 못하다고 할 수 있다. 그렇기 때문에 update 쿼리는 일반적으로 JPA의 더티 체킹을 이용하는 것이 좋다. 그에 따라 나도 기존의 save메서드를 없애고 더티체킹을 이용하도록 수정했다.

@Override
	public String updateMember(MemberDTO memberDTO) {
		Member findMember = memberRepository.findByEmail(memberDTO.getEmail()).get(0);
		findMember.updateMember(memberDTO.getPassword(), memberDTO.getName(), 
				memberDTO.getNickname(), memberDTO.isOfficialmark());
		
		return findMember.getEmail();
	}

특정 조인 검색 수정

기존에는 Querydsl의 리턴값으로 BoardDTO로 받았었는데 정확한 원인을 찾지못한 에러로 인해 Board 엔티티 형식으로 리턴받도록 수정했다. 또한 List를 Page로 변환하도록 했다.

		String keyword = dto.getKeyword();
		String type = dto.getType()!=null ? dto.getType() : "";
		
		// 페이지 정보
		int page = dto.getPage()-1;
		int size = dto.getSize();
		
		List<Board> list = query.select(board)
					.from(board)
					.join(board.member, member)
					.fetchJoin()
					.where(containTitle(type, keyword),containDescription(type, keyword),containBoth(type, keyword))
					.orderBy(board.bno.desc())
					.offset(page*size)
					.limit(size)
					.fetch();
		
		long count = query.selectFrom(board)
				.where(containTitle(type, keyword),containDescription(type, keyword),containBoth(type, keyword))
				.fetchCount();
		
		Sort sort = Sort.by("bno").descending();
		Pageable pageable = PageRequest.of(dto.getPage()-1, dto.getSize(), sort);
		
		return new PageImpl<>(list, pageable, count);

기존에 BoardDTO로 리턴받을 때는 아래와 같은 방식을 사용했는데

select(Protections.bean(BoardDTO.class, board, board.bno, board.title ...생략)

이상하게 Protections의 bean 방식만 가능했고 생성자나 @QueryProjection 방식 모두 제대로 작동하지 않았다. 또한 엔티티 전체를 select로 받으면서 board.bno나 board.title 같이 필드값도 같이 넣어줘야만 제대로 작동했다. 이로 인해 실제 쿼리의 select 절에 board 필드 값이 두번 들어가는 상황이 벌어졌는데 아직은 부족한 내 실력으로 원인을 찾을 수 없었다. 최대한 빨리 원인과 해결방법을 찾도록 할 것이다.
만약 이 문제에 대해 아시는 분들은 댓글을 남겨주시면 정말 감사하겠습니다.

Git

https://github.com/JINJAEHO/VoteProject/tree/main

profile
Java, Spring, SpringMVC, JPA, MyBatis

0개의 댓글