728x90

문제점 : 회원탈퇴 기능을 진행 중 다음의 에러를 마주했다.

 

org.springframework.dao.InvalidDataAccessApiUsageException:
Provided id of the wrong type for class com.min.board.model.Member. Expected: class com.min.board.model.MemberID, got class java.lang.Long; nested exception is java.lang.IllegalArgumentException: Provided id of the wrong type for class com.min.board.model.Member. Expected: class com.min.board.model.MemberID, got class java.lang.Long

 

 

findById()를 실행하면 나왔던 에러 내용인데, 에러 내용은 id가 MemberID인데 계속 Long 값을 넣어줘서 그렇다고 한다.

 

public interface JpaMemberRepository extends JpaRepository<Member, Long> {

기존 JPA를 구현한 리포지토리의 내용인데, 기본적으로 상속할 때

  • JpaRepository<엔티티 클래스, 엔티티 클래스의 기본키>

로 상속받아야한다.

 

그런데 프로젝트에서 식별자 클래스로 MemberID를 만들어놨었다.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MemberID implements Serializable {

    @Column(name = "id")
    private Long id;

    @Column(name = "username")
    private String username;
}

 

해결 : 리포지토리의 [엔티티 클래스의 기본키] 부분을 Long에서 MemberID로 고치고 해결됐다.

public interface JpaMemberRepository extends JpaRepository<Member, MemberID> {

 

728x90

문제 : 게시글 수정 작업 중 org.springframework.beans.NotReadablePropertyException 오류가 발생했다.

 

해결 : Thymeleaf에서 컨트롤러로 보내주는 파라미터 설정을 잘못하여 이를 고쳐줬다.

@Entity
@Data
@Table(name = "tb_board")
public class Board {

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

    @NotNull
    @Size(min = 2, max = 30, message = "제목은 2자 이상 30자 이하입니다.")
    private String title;

    @NotNull
    @Size(min = 1, message = "내용을 입력하세요.")
    private String content;

    @ManyToOne(targetEntity = Member.class, fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "writer", referencedColumnName = "username"),
            @JoinColumn(name = "writer_id", referencedColumnName = "id")
    })
    private Member member;
    private String image;
}
<form action="#" th:action="@{/board/form}" th:object="${board}" method="post">
	<input type="hidden" th:field="*{id}">
	<input type="hidden" th:field="*{member.id}">
	<input type="hidden" th:field="*{member.username}">
                .
                .
                .
	<div class="nav justify-content-end">
		<button type="submit" class="me-2 btn btn-primary">write</button>
	</div>
</form>
  • 타임리프에서 th:field="writer_id" 라고 작성해서 파라미터를 보내줬었는데, 참조하는 Entity의 필드명인 id를 적어주고 해결하였다.

 

'Web > Tymeleaf' 카테고리의 다른 글

[타임리프] Thymeleaf 정리  (0) 2021.12.18
728x90

문제점 : 게시판 프로젝트를 진행 중에 로그인과 게시판 기능을 일부 완성하고 연결하려하니 JPA 관련 오류가 발생했다.

  • 이유는 Entity객체에 JPA 사용을 위한 복합키 처리와 조인 처리를 안했던 것이었다.

해결 : 데이터베이스 설계를 다음 링크와 같이 바꾸었다. https://black-mint.tistory.com/21

 

[DataBase] MySQL 복합키 설계

문제점 : USERINFO의 PK(기본키)를 참조해서 BOARD에 FK를 만들려고하는데 계속 오류가 났다. 오류의 이유는 기존 USERINFO테이블의 PK를 id컬럼에만 적용하고는 BOARD 테이블에서 USERINFO테이블의 username컬

black-mint.tistory.com

그 후 기존 Entity클래스(Member, Board)에 @IdClass 어노테이션을 적용하기 위해 [Member, MemberID, Board] 3개의 클래스로 만들었다.

@Data
@Entity
@DynamicUpdate
@DynamicInsert
@Table(name = "tb_userinfo")
@IdClass(MemberID.class)
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Id
    @NotNull(message = "username을 입력하세요.")
    @Size(min = 1, max = 20, message = "username은 1자 이상 20자 이하입니다.")
    private String username;

    @NotNull(message = "암호를 입력하세요.")
    @Size(min = 6, max = 100, message = "암호는 6자 이상 100자 이하 입니다.")
    private String password;

    @NotNull
    @Size(min = 6, max = 45, message = "이메일은 6자 이상 45자 이하 입니다.")
    @Email
    private String email;

    @Column
    private String role;
}
  • @Data : lombok을 설치해야 사용 가능. Getter/Setter 등 자동 생성
  • @IdClass(식별자 클래스) : 식별자 클래스 지정 (복합키를 넣을 클래스)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MemberID implements Serializable {

    @Column(name = "id")
    private long id;

    @Column(name = "username")
    private String username;
}
  • 식별자 클래스는 public 이어야 하며, Serializable 인터페이스를 구현해야 한다. 또한, 기본 생성자 필수!
  • Entity객체와 필드명 같게 작성
  • @Data : 식별자 클래스는 equals(), hashCode()를 필수적으로 작성해줘야 한다. 이를 자동 생성
  • @AllArgsConstructor : 모든 필드 값을 파라미터로 받는 생성자를 생성
  • @NoArgsConstructor : 파라미터가 없는 생성자 생성
@Entity
@Data
@Table(name = "tb_board")
public class Board {

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

    @NotNull
    @Size(min = 2, max = 30, message = "제목은 2자 이상 30자 이하입니다.")
    private String title;

    @NotNull
    @Size(min = 1, message = "내용을 입력하세요.")
    private String content;

    @ManyToOne(targetEntity = Member.class, fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "writer", referencedColumnName = "username"),
            @JoinColumn(name = "writer_id", referencedColumnName = "id")
    })
    private Member member;
    private String image;
}
  • 게시판 - 사람 이기때문에 ManyToOne으로 구현. (여러 관계가 있으나, 주인 쪽이 FK를 관리하도록 설계하는 것이 좋다고 한다.)
  • @ManyToOne : 게시판 - 사람 관계이므로 @ManyToOne을 사용
  • @JoinColumns : 복합키 일 때 사용
  • @JoinColumn : 그림과 같이 참조하는 필드명과 참조받는 필드명을 작성
728x90

문제점 : USERINFO의 PK(기본키)를 참조해서 BOARD에 FK를 만들려고하는데 지속적으로 오류가 발생했다.

  • 오류의 이유는 기존 USERINFO테이블의 PK를 id컬럼에만 적용하고는 BOARD 테이블에서 USERINFO테이블의 username컬럼을 참조하려고해서 그랬다.

해결 : USERINFO테이블의 기본키를 id와 username 두 개를 설정하여 해결했다. (id를 해제하려했으나 Auto Increment는 PK가 적용된 컬럼만 된다고 한다.)

 

* 복합키 : 이렇게 2개의 컬럼을 PK로 지정하면 이를 복합키라고 한다.

 

수정 후 테이블 상태 (BOARD 테이블의 writer_id와 writer는 각각 USERINFO의 id와 username 컬럼을 참조한다.)

 

USERINFO 테이블

BOARD 테이블

+ Recent posts