TIL - 0523

스프링부트

게시글 상태 구현하기

  • 게시글 바로 삭제가 아닌 상태만 변경하기
    • 복구 요청, 보관 개념으로 상태만 변경해두었다가 일정 기간이 지났을 때 데이터베이스에서 삭제하도록 만들기
    • deleted 상태 : true / false로 구분
  • Question 엔티티 boolean을 저장하는 방법으로 해결
/* Entity */
@Entity
public class Qusetion {
	.
	.
	.
	@Column(nullable = false)
	private boolean deleted;	
}

  • Question 엔티티 boolean 대신 문자 혹은 0, 1로 저장하는 방법으로 해결
    • 방법1 : JPA 기능 중 컨버터 기능을 사용하면 됨 - javax.persistence.AttributeConverter, import javax.persistence.Converter
    • 방법2 : @Type(type = “org.hibernate.type.NumericBooleanType”) 사용하기
/* Entity */
@Entity
public class Qusetion {
	.
	.
	.
	@Convert(converter = BooleanToYNConverter)
	@Column(nullable = false)
	private boolean deleted;	
}

/* Entity Attribute Converter */
@Converter
public class BooleanToYNConverter implements AttributeConverter<Boolean, String> {

	@Override
    public String convertToDatabaseColumn(Boolean attribute) {
        return (attribute != null && attribute) ? "Y" : "N";
    }

    @Override
    public Boolean convertToEntityAttribute(String s) {
        return "Y".equals(s);
    }
}
  • 삭제 상태의 Question은 출력되지않도록 꺼내올 때 사용할 엔티티 쿼리메소드 정의하기
    • 컨벤션 : spring jpa query methods docs
    • 컨벤션에 맞춰서 메소드만 정의해두면 구현하지않더라도 JPA가 알아서 코드 완성 : 해당 메소드 실행하면 쿼리 실행
public interface QuestionRepository extends JpaRepository<Question, Long> {
	List<Question> findByDeletedIsFalse();
}
  • 게시글에 달린 댓글 중 삭제상태가 아닌 댓글만 찾아오기 : 조회할 때 댓글(조인컬럼)까지 가져옴
    • List<>로 반환받음 : stream 적용
    • 도메인 객체에 판단을 맡겨라 : 요청 메세지를 보내서 처리하도록 해야지, 꺼내서 처리하면 안됨(answer가 삭제되었는지는 answer가 알지 상태값을 가져와서 판단하면 안됨)
/* QuestionController.java */
@GetMapping("/{id}")
public String show(@PathVariable Long id, Model model) {
	.
	.
	.
	model.addAttribute("question", questionRepo.findById(id).get());
}

/* Question.java (Entity) */
@Entity
public class Question {
	.
	.
	.
	@OneToMany(mappedBy = "question")
	@OrderBy("id ASC")
	private List<Answer> answers;
	
	.
	.
	.
	public List<Answer> getValidAnswers() {
		return answers.filter(answer -> !answer.isDeleted()).collect(toList());
	}
}

/* /questions/show */

<article class="article" id="answer-1405">
	<div class="article-header">
		<div class="article-header-thumb">
			<img src="https://graph.facebook.com/v2.3/1324855987/picture" class="article-author-thumb" alt="">
		</div>
		<div class="article-header-text">
			<a href="/users/" class="article-author-name"></a>
				<a href="#answer-1434" class="article-header-time" title="퍼머링크"></a>
			</div>
		</div>
		<div class="article-doc comment-doc">
			<p></p>
		</div>

		<div class="article-util">
			<ul class="article-util-list">
				<li><a class="link-modify-article" href="/questions//answers//edit">수정</a></li>
				<li>
					<form class="delete-answer-form" action="/questions//answers/" method="POST">
						<input type="hidden" name="_method" value="DELETE">
						<button type="submit" class="delete-answer-button">삭제</button>
					</form>
				</li>
			</ul>
		</div>	
	</div>
</article>