Skip to content

Commit cf975fe

Browse files
committed
week3 hoonww 2
1 parent 21ea535 commit cf975fe

File tree

1 file changed

+272
-0
lines changed

1 file changed

+272
-0
lines changed

week3/BaseEntity, Builder Pattern.md

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
# BaseEntity
2+
3+
- 데이터의 생성 시간
4+
- 마지막으로 수정된 시간
5+
- 생성한 사람
6+
- 마지막으로 수정한 사람
7+
8+
에 대한 정보(컬럼)를 자동으로 만들어주는 추상 엔티티
9+
10+
~~~java
11+
@Getter
12+
@MappedSuperclass
13+
@EntityListeners(AuditingEntityListener.class)
14+
public abstract class BaseTimeEntity {
15+
16+
@CreatedDate
17+
@Column(updatable = false)
18+
private LocalDateTime createDate;
19+
20+
@LastModifiedDate
21+
private LocalDateTime lastModifiedDate;
22+
}
23+
~~~
24+
25+
- @MappedSuperClass<br>
26+
이 클래스를 상속받는 Entity에 이 BaseEntity의 컬럼들이 자동으로 등록시키겠다는 의미
27+
- @EntityListeners(AuditingEntityListener.class)<br>
28+
자동으로 값을 mapping시키는 auditing 기능을 사용하겠다는 의미
29+
30+
# 빌더 패턴(Builder Pattern)
31+
32+
생성자 패턴 중 하나<br>
33+
코드의 변경 과정을 하나씩 살펴보자
34+
35+
## 1. 생성자를 이용한 인스턴스 생성
36+
37+
~~~java
38+
// User.java
39+
@Entity
40+
@Getter
41+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
42+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
43+
public class User {
44+
45+
@Id
46+
@GeneratedValue(strategy = GenerationType.IDENTITY)
47+
@Column(name = "user_id")
48+
private Long id;
49+
50+
private String name;
51+
private String phoneNumber;
52+
private boolean pushAlarmAllow;
53+
54+
private String profileImage;
55+
56+
private Gender gender;
57+
58+
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
59+
private List<Oauth> oauths;
60+
61+
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
62+
private List<UserTaste> userTastes;
63+
64+
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
65+
private List<CustomIngredient> customIngredients;
66+
67+
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
68+
private List<UserIngredient> userIngredients;
69+
70+
public static User create(
71+
String name,
72+
String phoneNumber,
73+
boolean pushAlarmAllow,
74+
String profileImage,
75+
Gender gender,
76+
List<Oauth> oauths,
77+
List<UserTaste> userTastes,
78+
List<CustomIngredient> customIngredients,
79+
List<UserIngredient> userIngredients
80+
) {
81+
return new User(
82+
null,
83+
name,
84+
phoneNumber,
85+
pushAlarmAllow,
86+
profileImage,
87+
gender,
88+
oauths,
89+
userTastes,
90+
customIngredients,
91+
userIngredients
92+
);
93+
}
94+
}
95+
~~~
96+
97+
~~~java
98+
// UserRepositoryTest.java
99+
@Test
100+
@Transactional
101+
@DisplayName("유저 추가 테스트")
102+
public void createTest() {
103+
User user = User.create(
104+
"test",
105+
"010-1234-5678",
106+
false,
107+
"src/test_profile.jpg",
108+
Gender.M,
109+
new ArrayList<>(),
110+
new ArrayList<>(),
111+
new ArrayList<>(),
112+
new ArrayList<>()
113+
);
114+
User newUser = userRepository.save(user);
115+
116+
Optional<User> findUser = userRepository.findById(newUser.getId());
117+
118+
Assertions.assertFalse(newUser.equals(findUser));
119+
}
120+
~~~
121+
- 매우 조잡한 코드
122+
- 각각의 인자가 무엇을 의미하는지 모름
123+
- new ArrayList<>와 같이 빈 필드도 일일이 만들어줘야함
124+
125+
## 빌더 패턴 적용
126+
127+
### 빌더 패턴
128+
인스턴스 생성을 담당하는 Builder라는 것을 Entity 내부 클래스로 가진다.
129+
130+
~~~java
131+
// User.java
132+
@Entity
133+
@Getter
134+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
135+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
136+
public class User {
137+
138+
// User Entity 내부 컬럼 여러개 주저리주저리
139+
// 있다치고
140+
141+
private User(UserBuilder userBuilder){
142+
this.name = userBuilder.phoneNumber;
143+
this.phoneNumber = userBuilder.phoneNumber;
144+
this.pushAlarmAllow = userBuilder.pushAlarmAllow;
145+
this.profileImage = userBuilder.profileImage;
146+
this.gender = userBuilder.gender;
147+
this.oauths = userBuilder.oauths;
148+
this.userTastes = userBuilder.userTastes;
149+
}
150+
151+
public static class UserBuilder {
152+
private String name;
153+
private String phoneNumber;
154+
private boolean pushAlarmAllow;
155+
private String profileImage;
156+
private Gender gender;
157+
private List<Oauth> oauths;
158+
private List<UserTaste> userTastes;
159+
160+
// 기본적으로 User를 만들 때 꼭 필요한 정보도 지정할 수 있음
161+
public UserBuilder() {
162+
}
163+
164+
public UserBuilder setName(String name) {
165+
this.name = name;
166+
return this;
167+
}
168+
169+
public UserBuilder setPhoneNumber(String phoneNumber) {
170+
this.phoneNumber = phoneNumber;
171+
return this;
172+
}
173+
174+
public UserBuilder setPushAlarmAllow(boolean pushAlarmAllow){
175+
this.pushAlarmAllow = pushAlarmAllow;
176+
return this;
177+
}
178+
179+
public UserBuilder setProfileImage(String profileImage){
180+
this.profileImage = profileImage;
181+
return this;
182+
}
183+
184+
public UserBuilder setGender(Gender gender){
185+
this.gender = gender;
186+
return this;
187+
}
188+
189+
public UserBuilder setOauths(List<Oauth> oauths){
190+
this.oauths = oauths;
191+
return this;
192+
}
193+
194+
public UserBuilder setUserTastes(List<UserTaste> userTastes) {
195+
this.userTastes = userTastes;
196+
return this;
197+
}
198+
199+
public User build(){
200+
return new User(this);
201+
}
202+
}
203+
}
204+
~~~
205+
206+
~~~java
207+
// UserRepositoryTest.java
208+
@Test
209+
@Transactional
210+
@DisplayName("유저 추가 테스트")
211+
public void createTest() {
212+
User user = new User.UserBuilder()
213+
.setName("test")
214+
.setPhoneNumber("010-1234-5678")
215+
.setPushAlarmAllow(false)
216+
.setProfileImage("src/test_profile.jpg")
217+
.setGender(Gender.M)
218+
.build();
219+
User newUser = userRepository.save(user);
220+
221+
Optional<User> findUser = userRepository.findById(newUser.getId());
222+
223+
Assertions.assertFalse(newUser.equals(findUser));
224+
}
225+
~~~
226+
- 인스턴스 생성 시 각 인자가 무엇인지 알 수 있고(가독성이 좋다!)
227+
- 필요한 인자만 넣어 생성할 수 있다!
228+
- but 여전히 코드는 길다...
229+
230+
## Lombok @Builder
231+
232+
롬복 웨않쓺?
233+
234+
~~~java
235+
// User.java
236+
@Entity
237+
@Getter
238+
@Builder
239+
@AllArgsConstructor(access = AccessLevel.PRIVATE)
240+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
241+
public class User {
242+
243+
// User Entity 내부 컬럼 여러개 주저리주저리
244+
// 있다치고
245+
246+
// 여기있던 아주 긴 코드
247+
// private 생성자와
248+
// static class UserBuilder가
249+
// @Builder만 써주는 것으로 대체되었다
250+
}
251+
~~~
252+
253+
~~~java
254+
// UserRepositoryTest.java
255+
@Test
256+
@Transactional
257+
@DisplayName("유저 추가 테스트")
258+
public void createTest() {
259+
User user = User.builder()
260+
.name("test")
261+
.phoneNumber("010-1234-5678")
262+
.pushAlarmAllow(false)
263+
.profileImage("src/test_profile.jpg")
264+
.gender(Gender.M)
265+
.build();
266+
User newUser = userRepository.save(user);
267+
268+
Optional<User> findUser = userRepository.findById(newUser.getId());
269+
270+
Assertions.assertFalse(newUser.equals(findUser));
271+
}
272+
~~~

0 commit comments

Comments
 (0)