https://dongseokstudy2.tistory.com/121?category=916641
스프링 아이템기능 구현, 단어 뒤집기, 파파고 API
프로젝트 기능중 채팅방에서 유저가 아이템을 쓸 수 있는 기능이 있다. 유저가 아이템을 사용하기 위해선 아이템을 구매할 수 있어야 한다. @GetMapping("/mypage/{item}") @ApiOperation(value = "아이템 구매"
dongseokstudy2.tistory.com
전에 만들었던 아이템관련 코드들은 위에 정리되어있다.
기존 코드의경우 코드가 너무 길고 switch문과 if문이 많이 들어가있기도해서 이점을 고쳐보려한다.
case "onlyMe":
buyitem.setOnlyMe(buyitem.getOnlyMe() + 1);
itemRepository.save(buyitem);
itemBuy(user, onlyMePrice, "나만 말하기");
break;
private void itemBuy(User user, Long price, String item) {
if (user.getTotalPoint() >= price) {
user.setTotalPoint(user.getTotalPoint()-price);
userRepository.save(user);
Point point = new Point(item + " 구매", -price, user.getTotalPoint(), user);
pointRepository.save(point);
} else {
throw new LackPointException("보유한 포인트가 부족합니다");
}
}
기존 코드 switch문에 한문단과 그안에있는 itemBuy메소드를 가져왔다.
itemBuy는 유저엔티티와 가격 그리고 아이템 이름을 받아와 유저의 포인트에 아이템의 가격만큼 뺴주고
포인트 내역을 만들때는 아이템이름과 가격을 사용해서 내역을 만든다.
기존 테이블구조는 유저 - 아이템이 OneToOne관계로 아이템 테이블에는 Integer형 변수명으로 아이템의 이름이 있고 해당하는 아이템의 갯수가 있다.
우선 코드를 줄이기 위해 아이템의 가격과 이름을 enum값으로 바꾸기로 했다.
@NoArgsConstructor
@Getter
public enum ItemType {
bigFont("bigFont", 100L, "내 글자 크게 만들기"),
onlyMe("onlyMe", 100L, "나만 말하기"),
myName("myName", 100L, "모두 내이름으로 바꾸기"),
papago("papago", 100L, "나만빼고 랜덤으로 번역하기"),
reverse("reverse", 100L, "나만빼고 반대로 말하기"),
exBuy("exBuy", 100L, "경험치 구매");
private String itemCode;
private Long price;
private String itemName;
ItemType(String itemCode, Long price, String itemName) {
this.itemCode = itemCode;
this.price = price;
this.itemName = itemName;
}
}
각각 타입에는 itemCode(프론트와 주고받을 이름), price(아이템 가격), itemName(아이템의 이름) 이 담겨있다.
이제 아이템의 테이블 구조를 바꿔줄 차례다
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Entity
@Table(name = "item")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column
private String itemCode;
@Column
private Long cnt;
@ManyToOne
@JoinColumn(name = "userId")
private User user;
public void setCnt(Long cnt) {
this.cnt = cnt;
}
public Item(String itemCode, Long cnt, User user) {
this.itemCode = itemCode;
this.cnt = cnt;
this.user = user;
}
기존 단순히 private Integer ItemName; 이렇게 있는것에서 아이템의 코드와 갯수 그리고 주인인 유가 들어가게 설계했다.
이렇게 바꾸고 난후 유저와 아이템을 OneToMany로 일대다관계를 맺어준다.
@Transactional
public void buyItem(ItemType item, User user) {
if (user.getTotalPoint() < item.getPrice()) {
throw new LackPointException("보유한 포인트가 부족합니다");
}
user.setTotalPoint(user.getTotalPoint() - item.getPrice());
userRepository.save(user);
if (item.getItemCode().equals("exBuy")) {
user.setEx((int) (user.getEx() + item.getPrice()));
userRepository.save(user);
} else {
Item userItem = itemRepository.findByUser_IdAndItemCode(user.getId(), item.getItemCode());
userItem.setCnt(userItem.getCnt() + 1);
itemRepository.save(userItem);
}
Point point = new Point(item.getItemName() + "구매", -item.getPrice(), user.getTotalPoint(), user);
pointRepository.save(point);
}
아이템 구매의 서비스 로직이다.
위에서 유저의 포인트가 아이템 가격보다 싼지 확인하고 유저의 포인트롤 아이템의 가격만큼 차감하고
exBuy의 경우는 경험치 구매이기때문에 다른 방식으로 save를 하고 나머지 아이템들의 경우 그 아이템의 갯수만 조절해주면된다. 이렇게 할경우 코드가 훨씬 짧아진다.
//아이템 사용
@Transactional
public void useItem(ItemType item, User user) {
Item userItem = itemRepository.findByUser_IdAndItemCode(user.getId(), item.getItemCode());
if (userItem.getCnt() > 0) {
userItem.setCnt(userItem.getCnt() - 1);
itemRepository.save(userItem);
} else {
throw new ItemNotFoundException("아이템이 없습니다");
}
}
아이템 사용 로직의 경우도 기존 코드에비해 훨씬 짧아진것을 확인할 수 있다.
기존의 단순 if elseif를 반복하여 각각 if문에서 아이템구매를 해주는 방식은 애초에 의존성주입도 안되있어 아이템의 가격이 바뀌거나 무언가 추가될경우 서비스코드에 무언가를 수정해주어야하는데 리팩터링된 코드는 enum의 값을 수정해주면 OK다.
'공부기록 > 자바 스프링' 카테고리의 다른 글
Querydsl 공부 <환경 설정 및 기본 엔티티 설정> (0) | 2022.05.26 |
---|---|
JPA 연관관계 (0) | 2022.04.17 |
스프링 아이템기능 구현, 단어 뒤집기, 파파고 API (0) | 2022.03.12 |
스프링 룰렛기능 만들기 (가챠시스템), 자바 난수 설정, 확률설정 (0) | 2022.03.09 |
스프링 배팅시스템 만들기 (트위치 배팅시스템 참고) (0) | 2022.03.08 |