728x90

2023.12.26 - [DB(MySQL, MongoDB, Redis, Kafka)/MySQL] - MySQL 테스트를 위한 SNS서비스 회원정보 등록

 

MySQL 테스트를 위한 SNS서비스 회원정보 등록

들어가며, 간단한 SNS 모델링을 통해 MySQL의 기능들을 사용해 볼 계획입니다. 아래 기술들을 활용해 Layered 구조로 작성했습니다. Java 17 Spring Boot 3.x MySQL 8.x 회원정보 등록을 구현 회원정보 아이디

wooltech.tistory.com

2023.12.26 - [DB(MySQL, MongoDB, Redis, Kafka)/MySQL] - MySQL 테스트를 위한 SNS서비스 회원정보 조회

 

MySQL 테스트를 위한 SNS서비스 회원정보 조회

2023.12.26 - [DB(MySQL, MongoDB, Redis, Kafka)/MySQL] - MySQL 테스트를 위한 SNS서비스 회원정보 등록 MySQL 테스트를 위한 SNS서비스 회원정보 등록 들어가며, 간단한 SNS 모델링을 통해 MySQL의 기능들을 사용해

wooltech.tistory.com

 

앞서 만든 내용에 회원 이름이 변경 가능하도록만 수정하고, 변경이력 조회를 진행했습니다.

 

public void changeNickname(String other) {
    validateNickname(other);
    nickname = other;
}

 

닉네임이 변경가능하도록 member 객체에 changeNickname 메서드를 따로 만들면 됩니다.

 

public void changeNickname(Long id, String nickname) {
    var member = memberRepository.findById(id)
            .orElseThrow(() -> new IllegalArgumentException("해당하는 회원이 없습니다."));
    member.changeNickname(nickname);
    memberRepository.save(member);
}

 

WriteService에서는 리포지토리에 id값으로 조회를 한 뒤, 닉네임을 바꾸고 다시 저장하게 됩니다.

 

private Member update(Member member) {
    var sql = "update " + TABLE_NAME + " set nickname = :nickname where id = :id";
    SqlParameterSource params = new BeanPropertySqlParameterSource(member);
    namedParameterJdbc.update(sql, params);
    return member;
}

 

리포지토리에 update메서드를 통해 sql쿼리로 update된 member객체를 반환합니다.

 

    @PostMapping("/members/{id}/nickname")
    public MemberDto changeNickname(@PathVariable Long id, @RequestBody String nickname) {
        memberWriteService.changeNickname(id, nickname);
        return memberReadService.getMember(id);
    }
}

 

Controller는 WriteService를 통해 수정하고, ReadService를 통해 조회한 값을 반환합니다.

 

회원이름 변경내역

 

create table Member
(
    id int auto_increment,
    email varchar(20) not null,
    nickname varchar(20) not null,
    birthdate date not null,
    createdAt datetime not null,
    constraint member_id_uindex
        primary key (id)
);


create table MemberNicknameHistory
(
    id int auto_increment,
    memberId int not null,
    nickname varchar(20) not null,
    createdAt datetime not null,
    constraint memberNicknameHistory_id_uindex
        primary key (id)
);

 

변경이력은 기존의 회원정보 테이블과 데이터 중복을 피하기 위해 분리했습니다.
다만, 변경이력의 memberId는 member테이블의 id를 참조하고 있는데도 FK로 지정하고 있지 않습니다.
필수는 아니지만 데이터의 무결성을 위해 지정하는 것이 좋을 것 같습니다.

 

@Getter
public class MemberNickNameHistory {
    private final Long id;
    private final Long memberId;
    private final String nickname;

    private final LocalDate createdAt;

    @Builder
    public MemberNickNameHistory(Long id, Long memberId, String nickname, LocalDate createdAt) {
        this.id = id;
        this.memberId = Objects.requireNonNull(memberId);
        this.nickname = Objects.requireNonNull(nickname);
        this.createdAt = createdAt == null ? LocalDate.now() : createdAt; // 로그를 위해 생성시간 추가
    }
public record NickNameHistoryDto (
        Long id,
        Long memberId,
        String nickname,
        LocalDate createdAt
){
}

 

엔티티와 Dto는 기존 member와 같은 형식으로 작성했습니다.

 

@Repository
@RequiredArgsConstructor
public class MemberNickNameHistoryRepository {

    private final NamedParameterJdbcTemplate namedParameterJdbc;

    private static final String TABLE_NAME = "MemberNickNameHistory";
    public static final RowMapper<MemberNickNameHistory> rowMapper = (rs, rowNum) -> MemberNickNameHistory
            .builder()
            .id(rs.getLong("id"))
            .memberId(rs.getLong("memberId"))
            .nickname(rs.getString("nickname"))
            .createdAt(rs.getObject("createdAt", LocalDate.class))
            .build();

    public List<MemberNickNameHistory> findAllByMemberId(Long memberId) {
        /*
        select * from Member where memberId = :memberId;
         */
        var sql = "select * from " + TABLE_NAME + " where memberId = :memberId";
        var params = new MapSqlParameterSource()
                .addValue("memberId", memberId);

        return namedParameterJdbc.query(sql, params, rowMapper);
    }

    public MemberNickNameHistory save(MemberNickNameHistory memberNickNameHistory) {
        if (memberNickNameHistory.getId() == null) {
            return insert(memberNickNameHistory);
        }
        throw new IllegalArgumentException("MemberNickNameHistory는 수정할 수 없습니다.");
    }

    private MemberNickNameHistory insert(MemberNickNameHistory memberNickNameHistory) {
        SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(namedParameterJdbc.getJdbcTemplate())
                .withTableName(TABLE_NAME)
                .usingGeneratedKeyColumns("id");
        SqlParameterSource params = new BeanPropertySqlParameterSource(memberNickNameHistory);

        var id = simpleJdbcInsert.executeAndReturnKey(params).longValue();

        return MemberNickNameHistory.builder()
                .id(id)
                .memberId(memberNickNameHistory.getMemberId())
                .nickname(memberNickNameHistory.getNickname())
                .createdAt(memberNickNameHistory.getCreatedAt())
                .build();
    }
}

 

Repository에서 데이터 액세스하는 메서드를 구현하고 있습니다.
sql쿼리가 실행되고 그 결과가 RowMapper를 통해 객체로 반환됩니다. 

Insert 역시 SimpleJdbcInsert를 사용하여 데이터를 삽입하고 있습니다.
그리고 생성된 id 키값을 가져와 MemberNickNameHistory객체를 빌더패턴으로 설정하고 있습니다.

 

Read 및 Write 서비스에서는 동일한 방식으로 기능을 구현하고 Controller를 통해 HTTP요청을 받고 있습니다.

 

 

 

 

 

+ Recent posts