Skip to content

Commit

Permalink
feat: MeetingEntity와 MeetingRepository 개발 (#8)
Browse files Browse the repository at this point in the history
* feat: 미팅 도메인을 구현한다.

* feat: MeetingRepository를 구현한다.

* chore: auto_increment id 생성 전략을 추가한다.

* feat: meeting의 Id 생성 전략을 설정한다.

* feat: meeting의 검증 로직들을 추가한다.

1. 모임 소개는 10~200자 사이여야 한다.
2. 참여자 수는 2~6명 사이여야 한다.
3. 모임의 제목은 2~32자 사이여야 한다.

* chore: Test H2 DB의 방언을 변경한다.

* test: MeetingFixture를 구현하고, MeetingRepository를 테스트한다.
  • Loading branch information
ddingmin authored Dec 29, 2023
1 parent a8376fa commit 59ae582
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 3 deletions.
71 changes: 71 additions & 0 deletions src/main/java/net/teumteum/meeting/domain/Meeting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package net.teumteum.meeting.domain;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import net.teumteum.core.entity.TimeBaseEntity;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Meeting extends TimeBaseEntity {

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

@Column(name = "title", length = 32)
private String title;

@Column(name = "host_user_id")
private Long hostUserId;

@ElementCollection
private List<Long> participantUserIds = new ArrayList<>();

@Column(name = "topic")
@Enumerated(EnumType.STRING)
private Topic topic;

@Column(name = "introduction", length = 200)
private String introduction;

@Embedded
private MeetingArea meetingArea;

@Column(name = "number_of_recruits")
private int numberOfRecruits;

@Embedded
private PromiseDateTime promiseDateTime;

@ElementCollection
private List<String> imageUrls = new ArrayList<>();

@PrePersist
private void assertField() {
assertTitle();
assertNumberOfRecruits();
assertIntroduction();
}

private void assertIntroduction() {
Assert.isTrue(introduction.length() >= 10 && introduction.length() <= 200, "모임 소개는 10자 ~ 200자 사이가 되어야 합니다. [현재 입력된 모임 소개] : " + introduction);
}

private void assertNumberOfRecruits() {
Assert.isTrue(numberOfRecruits >= 2 && numberOfRecruits <= 6, "참여자 수는 2명 ~ 6명 사이가 되어야 합니다. [현재 입력된 참여자 수] : " + numberOfRecruits);
}

private void assertTitle() {
Assert.isTrue(title.length() >= 2 && title.length() <= 32, "모임 제목은 2자 ~ 32자 사이가 되어야 합니다. [현재 입력된 모임 제목] : " + title);
}

}
24 changes: 24 additions & 0 deletions src/main/java/net/teumteum/meeting/domain/MeetingArea.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package net.teumteum.meeting.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class MeetingArea {

@Column(name = "city")
private String city;

@Column(name = "street")
private String street;

@Column(name = "zip_code")
private String zipCode;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.teumteum.meeting.domain;

import org.springframework.data.jpa.repository.JpaRepository;


public interface MeetingRepository extends JpaRepository<Meeting, Long> {

}
23 changes: 23 additions & 0 deletions src/main/java/net/teumteum/meeting/domain/PromiseDateTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.teumteum.meeting.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalTime;

@Getter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class PromiseDateTime {

@Column(name = "promise_date")
private LocalDate date;

@Column(name = "promise_time")
private LocalTime time;
}
10 changes: 10 additions & 0 deletions src/main/java/net/teumteum/meeting/domain/Topic.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.teumteum.meeting.domain;

public enum Topic {

고민_나누기,
모여서_작업,
스터디,
사이드_프로젝트,

}
2 changes: 1 addition & 1 deletion src/main/resources/db/migration/V1__create_users.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
create table if not exists users(
id bigint not null auto_increment,
certificated boolean,
manner_temperature integer,
mbti varchar(4),
character_id bigint,
id bigint not null,
birth varchar(10),
name varchar(10),
goal varchar(50),
Expand Down
32 changes: 32 additions & 0 deletions src/main/resources/db/migration/V2__create_meeting.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
create table if not exists meeting
(
id bigint not null
primary key auto_increment,
number_of_recruits int null,
promise_date date null,
promise_time time(6) null,
created_at timestamp(6) not null,
host_user_id bigint null,
updated_at timestamp(6) not null,
title varchar(32) null,
introduction varchar(200) null,
city varchar(255) null,
street varchar(255) null,
zip_code varchar(255) null,
topic enum ('고민_나누기', '모여서_작업', '스터디', '사이드_프로젝트') null
);

create table if not exists meeting_image_urls
(
meeting_id bigint not null,
image_urls varchar(255) null,
foreign key (meeting_id) references meeting (id)
);

create table if not exists meeting_participant_user_ids
(
meeting_id bigint not null,
participant_user_ids bigint null,
foreign key (meeting_id) references meeting (id)
);

70 changes: 70 additions & 0 deletions src/test/java/net/teumteum/meeting/domain/MeetingFixture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package net.teumteum.meeting.domain;

import lombok.Builder;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

public class MeetingFixture {

public static Meeting getMeetingWithId(Long id) {
return newMeetingByBuilder(MeetingBuilder.builder()
.id(id)
.build());
}

public static Meeting getDefaultMeeting() {
return newMeetingByBuilder(MeetingBuilder.builder().build());
}

public static Meeting newMeetingByBuilder(MeetingBuilder meetingBuilder) {
return new Meeting(
meetingBuilder.id,
meetingBuilder.title,
meetingBuilder.hostUserId,
meetingBuilder.participantUserIds,
meetingBuilder.topic,
meetingBuilder.introduction,
meetingBuilder.meetingArea,
meetingBuilder.numberOfRecruits,
meetingBuilder.promiseDateTime,
meetingBuilder.imageUrls
);
}

@Builder
public static class MeetingBuilder {
@Builder.Default
private Long id = 0L;

@Builder.Default
private String title = "모임 제목";

@Builder.Default
private Long hostUserId = 0L;

@Builder.Default
private List<Long> participantUserIds = new ArrayList<>(List.of(0L));

@Builder.Default
private Topic topic = Topic.스터디;

@Builder.Default
private String introduction = "모임에 대한 간단한 설명입니다.";

@Builder.Default
private MeetingArea meetingArea = new MeetingArea("서울특별시", "강남구", "강남대로 390");

@Builder.Default
private int numberOfRecruits = 3;

@Builder.Default
private PromiseDateTime promiseDateTime = new PromiseDateTime(LocalDate.of(2023, 1, 1), LocalTime.of(12, 0));

@Builder.Default
private List<String> imageUrls = new ArrayList<>(List.of("https://www.google.com"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package net.teumteum.meeting.domain;

import jakarta.persistence.EntityManager;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

@DataJpaTest
@DisplayName("MeetingRepository 클래스의")
class MeetingRepositoryTest {

@Autowired
private MeetingRepository meetingRepository;

@Autowired
private EntityManager entityManager;

@Nested
@DisplayName("save 메소드는")
class Save_method {

@Test
@DisplayName("올바른 MeetingEntity가 들어오면, 모임 저장에 성공한다.")
void Save_success_if_correct_meeting_entered() {
// given
var newMeeting = MeetingFixture.getDefaultMeeting();

// when
var result = Assertions.catchException(() -> meetingRepository.saveAndFlush(newMeeting));

// then
Assertions.assertThat(result).isNull();
}
}

@Nested
@DisplayName("findById 메소드는")
class FindById_method {

@Test
@DisplayName("저장된 모임의 id로 조회하면, 모임을 반환한다.")
void Find_success_if_exists_meeting_id_input() {
// given
var id = 1L;
var existsMeeting = MeetingFixture.getMeetingWithId(id);

meetingRepository.saveAndFlush(existsMeeting);
entityManager.clear();

// when
var result = meetingRepository.findById(id);

// then
Assertions.assertThat(result)
.isPresent()
.usingRecursiveComparison()
.ignoringFields("value.createdAt", "value.updatedAt")
.isEqualTo(Optional.of(existsMeeting));
}
}

}
2 changes: 1 addition & 1 deletion src/test/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ spring.datasource.driver-class-name = org.h2.Driver
spring.datasource.url = jdbc:h2:mem:test;MODE=MySQL;DATABASE_TO_LOWER=TRUE

spring.jpa.hibernated.ddl-auto = validate
spring.jpa.database-platform = org.hibernate.dialect.H2Dialect
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect

spring.datasource.hikari.maximum-pool-size = 4
spring.datasource.hikari.pool-name = H2_TEST_POOL
Expand Down
35 changes: 34 additions & 1 deletion src/test/resources/schema.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
create table if not exists users(
id bigint not null auto_increment,
certificated boolean,
manner_temperature integer,
mbti varchar(4),
character_id bigint,
id bigint not null,
birth varchar(10),
name varchar(10),
goal varchar(50),
Expand Down Expand Up @@ -32,3 +32,36 @@ create table if not exists users_street(
street varchar(255),
foreign key (users_id) references users(id)
);

create table if not exists meeting
(
id bigint not null
primary key auto_increment,
number_of_recruits int null,
promise_date date null,
promise_time time(6) null,
created_at timestamp(6) not null,
host_user_id bigint null,
updated_at timestamp(6) not null,
title varchar(32) null,
introduction varchar(200) null,
city varchar(255) null,
street varchar(255) null,
zip_code varchar(255) null,
topic enum ('고민_나누기', '모여서_작업', '스터디', '사이드_프로젝트') null
);

create table if not exists meeting_image_urls
(
meeting_id bigint not null,
image_urls varchar(255) null,
foreign key (meeting_id) references meeting (id)
);

create table if not exists meeting_participant_user_ids
(
meeting_id bigint not null,
participant_user_ids bigint null,
foreign key (meeting_id) references meeting (id)
);

0 comments on commit 59ae582

Please sign in to comment.