- 이번 시간에는 JPA를 이용하여 테이블을 생성해보도록 하겠습니다.
- Blog 테이블은 크게 User, Board, Reply로 구분하여 생성할 것입니다.
- 우선 패키지를 새로 생성하고 해당 패키지 안에 세 가지 클래스를 생성해주었습니다.
- 이후 User 클래스 먼저 다음과 같이 구현해주었습니다.
- 하나씩 살펴보자면, 먼저 id 부분의 @id 어노테이션은 해당 열을 테이블에서 기본키(Primary key)로 사용하겠다는 것이며,
- id 열은 auto_increment 즉, 테이블에 값을 추가할 때 따로 지정해주는 것이 아니라 자동적으로 넘버링 값이 들어가도록 설정할 것이기 때문에 @GeneratedValue 어노테이션을 통해 해당 열의 넘버링 전략을 지정해준 것입니다.
- 다음으로 username과 password, email 열은 테이블에서 널(Null) 값을 허용하지 않기 위해 @Column 어노테이션의 nullable 속성을 사용해주었으며,
- length 속성을 통해 길이 또한 지정해주었습니다. 여기서 password 열의 길이를 100으로하여 상대적으로 긴 길이를 준 이유는 이후 해시를 사용하여 암호화를 진행할 것이기 때문입니다.
- 다음으로 role 열은 테이블에서 사용자의 역할을 구분지어 저장하는 열로써 오타를 방지하고 범위를 지정하기 위해서는 Enum을 사용하여 정의하는 것이 바람직하나, 여기서는 String을 사용하였습니다.
- 추가로 role 열의 기본값을 지정하기 위해서 @ColumnDefault 어노테이션을 사용하였습니다.
- 다음으로 createDate 열은 테이블에 데이터가 입력될 시 자동으로 입력 시간이 저장될 수 있도록 @CreationTimestamp 어노테이션을 사용하였습니다.
- 추가로 User 클래스에 붙은 @Entity 어노테이션은 해당 클래스를 테이블로 생성하기 위해서 사용한 것입니다.
- 테이블 클래스를 구현하였으니 이제 실제로 잘 테이블이 잘 생성되는지 확인해보아야 할 것입니다.
- 그전에 우선 application.yml 파일에서 'ddl-auto' 부분이 'create'로 설정되어 있는지 확인해야 합니다.
- 이는 만약 기존에 똑같은 이름의 테이블이 있다고 하더라도 프로젝트를 재실행 할 때마다 테이블을 새로 만들겠다는 것입니다.
- 따라서 우리는 최초에만 create로 설정하고, 그 이후부터는 'update'로 설정하므로써 기존에 있던 데이터를 날리지 않고 추가하는 형식으로 설정할 수 있습니다.
- 이제 작업 관리자의 서비스 탭에서 MySQL이 서비스 중인 것을 확인하고, 프로젝트를 실행하면 다음과 같이 콘솔창에 테이블 생성을 위한 sql문이 출력되는 것을 확인할 수 있습니다.
- 이는 우리가 application.yml 파일에서 설정하였던 'show-sql' 부분을 true 값으로 설정했기 때문입니다. 또한 원래는 모든 sql 구문이 한 줄로 출력되는데, 이 또한 우리가 'hibernate.format_sql' 부분을 true 값으로 설정했기 때문에 정렬되어 출력된 것입니다.
- 추가로 이전 시간에 설명하지 않았던 부분이 아래와 같은 부분인데
- 여기서 'physical-strategy'는 테이블을 생성하며 필드를 만들 때, 해당 필드의 이름을 우리가 지정한 변수 이름 그대로 사용하겠다는 것입니다. 즉 테이블에는 id, username, password 등의 이름이 그대로 사용될 것입니다.
- 다음으로 'use-new-id-generator-mappings'는 JPA가 사용하는 기본 넘버링 전략을 사용할 것인지를 설정하는 부분으로 false로 설정하게 되면 JPA가 사용하는 기본 넘버링 전략을 따라가지 않겠다는 의미입니다.
- 즉 우리가 위에서 id 열에 설정했던 @GerneratedValue 어노테이션과 관련된 부분입니다.
- 설명은 여기까지하고 실제로 테이블이 생성되었는지 확인해보겠습니다.
- Workbench를 열고 Connection에 접속하여 보면 다음과 같이 테이블이 생성된 것을 확인할 수 있을 것입니다.
- 추가로 다음과 같이 명령어를 입력하여 테이블의 형태를 결과로 확인할 수 있습니다.
- 만약 테이블 열의 이름을 바꾸고 싶다면 우리는 코드만 수정함으로써 손쉽게 수정할 수 있습니다. 여기서 알 수 있는 JPA의 ORM이란 기능은 JAVA 혹은 다른 모든 언어로 작성된 Object를 테이블로 매핑해주는 기능입니다.
- 이번에는 Borad 테이블을 생성해보도록 하겠습니다.
- 우선 위에서 생성한 Board 클래스를 다음과 같이 구현해주었습니다.
- 이번엔 위에서 설명한 내용들은 생략하고 설명하겠습니다.
- 먼저 content 열은 게시글의 내용을 저장할 공간으로, 이후 웹 에디터를 사용하기 위해 Summbernote 라이브러리를 사용하게 될 텐데, 이는 <html> 태그가 섞여서 디자인되므로 용량이 커질 수 있어 @Lob(Large Object) 어노테이션을 사용해주었습니다.
- @Lob 어노테이션은 말 그대로 대용량의 데이터를 저장하기 위해 사용합니다.
- 아래 구문은 게시글을 작성한 사용자가 누구인지 저장하기 위해 User 테이블과 연결하기 위한 것으로, @ManyToOne 어노테이션은 한 명의 사용자가 여러 게시글을 작성할 수 있다는 연관관계를 표현한 것이며,
- @JoinColumn 어노테이션은 User 테이블과 Join을 수행할 시 생성될 외래키(Foreign key) 필드의 이름을 지정하기 위해 사용하였습니다.
- 이 또한 JPA의 ORM 기능 중 하나로, 데이터베이스의 경우 오브젝트를 저장할 수 없으나 자바는 오브젝트를 저장할 수 있기 때문에 위와 같은 작업이 가능하게 됩니다.
- 이제 프로젝트를 실행하여 테이블을 생성한 뒤, Workbench를 살펴보면 다음과 같이 테이블이 잘 생성된 것을 확인할 수 있습니다.
- 또한 데이터베이스는 오브젝트를 저장할 수 없으므로 다음과 같이 자동적으로 외래키로 설정되는 것을 확인할 수 있습니다.
- 이번에는 Reply 테이블을 생성하도록 하겠습니다.
- 마찬가지로 이전에 생성하였던 Reply 클래스를 다음과 같이 구현해주었습니다.
- Reply 테이블 또한 댓글과 관련된 테이블로써 작성자와 작성된 게시글에 대한 정보를 포함하고 있어야 하므로 외래키로 User 테이블과 Board 테이블의 id 값을 사용할 것입니다.
- 따라서 아래와 같이 구현해주었으며, 여러 댓글이 하나의 게시글에 달릴 수 있고, 여러 댓글이 한 명의 사용자에 의해 작성될 수 있으므로 @ManyToOne의 연관관계를 설정해주었습니다.
- 이후 프로젝트를 재실행하고 테이블이 잘 생성되었는지 확인합니다.
- 이렇게 총 세 가지 테이블을 구현하고 생성하였으나 아직까지 테이블을 완벽하게 설계한 것은 아닙니다.
- 테이블을 완벽하게 설계하기 위해서는 연관관계의 주인(외래키를 가진 오브젝트)에 대한 이해가 필요합니다.
- 우리가 위에서 설계한 테이블 중 Board 테이블에 대해서 생각해보면, Board 테이블은 현재 User 테이블의 id 값만 외래키로 가지고 있지만 사실 Reply 테이블과도 연결되어 있어야 합니다.
- 그 이유는 어떠한 게시글을 출력할 때에는 해당 게시글의 작성자 이름 뿐만 아니라 게시글에 작성된 댓글 또한 출력되어야 하기 때문입니다.
- 그런데 여기서 댓글은 하나의 게시글에 여러 개가 달릴 수 있으며 따라서 우리는 Board 테이블에 다음과 같이 열을 추가해줄 수 있습니다.
- 여기서 @JoinColumn 어노테이션 지정하지 않은 이유는, Board 테이블은 댓글 또한 출력해야하기 때문에 Reply 테이블과 연결되어야 하는 것은 맞지만 이를 Join을 통해 외래키로 설정할 경우 하나의 게시물에는 여러개의 댓글이 작성될 수 있기 때문에 Board 테이블에 외래키로 생성된 열에 둘 이상의 값이 저장되게 되면서 데이터베이스에서 데이터의 원자성을 해치는 결과를 초래하게 되기 때문입니다.
- 추가로 @OneToMany 어노테이션의 'mappedBy' 속성을 사용하여 해당 변수는 연관관계의 주인이 아니다. 즉, 외래키가 아니라는 것을 알려주어 데이터베이스에서 열을 따로 생성하지 않도록 설정해주었습니다.
- 참고로 mappedBy 속성에 지정된 값은 기존 Reply 테이블에서 설정한 필드 이름입니다.
- 추가로 @ManyToOne 어노테이션의 기본 전략은 다음과 같이 'EAGER'로 되어있습니다.
- EAGER이란 테이블을 SELECT하여 출력할 때, 해당 열에 대한 정보를 무조건 가져오겠다는 의미입니다. 즉 위의 경우는 게시글이 출력될 때 작성자 이름도 반드시 출력되야 하므로 속성을 생략하거나 위처럼 EAGER로 설정한 것입니다.
- 이와 달리 @OneToMany 어노테이션의 경우 기본 전략은 다음과 같이 'LAZY'로 설정되어 있습니다.
- LAZY란 EAGER과 달리 반드시 출력해야하는 것이 아닌 선택적으로 출력하고자 할 때 사용하는 방식입니다.
- 즉, @OneToMany 특성상 출력해야할 데이터가 상당히 많아질 수도 있기 때문에 이로 인한 과부화를 사전에 방지하기 위해 기본 방식이 LAZY로 설정되어 있는 것입니다.
- 하지만 우리가 만드는 블로그의 경우 이를 LAZY로 설정하지 않고 EAGER로 설정하여 게시글을 출력할 시 작성자에 대한 데이터와 댓글에 대한 데이터를 모두 가져와 출력할 수 있도록 할 것입니다.
📌 References
- https://www.youtube.com/watch?v=6ynr-XAI-rk&list=PL93mKxaRDidECgjOBjPgI3Dyo8ka6Ilqm&index=20
- https://www.youtube.com/watch?v=MJSMvETSE7E&list=PL93mKxaRDidECgjOBjPgI3Dyo8ka6Ilqm&index=22
- https://www.youtube.com/watch?v=u-E9TH4ZaEA&list=PL93mKxaRDidECgjOBjPgI3Dyo8ka6Ilqm&index=23
- https://www.youtube.com/watch?v=DtMmXQl4_hw&list=PL93mKxaRDidECgjOBjPgI3Dyo8ka6Ilqm&index=24
'🚗 Backend Toy Project > 스프링 부트 게시판' 카테고리의 다른 글
[스프링부트 게시판] 9. SELECT 테스트 (0) | 2022.05.03 |
---|---|
[스프링부트 게시판] 8. 회원가입을 위한 insert 테스트 (0) | 2022.05.02 |
[스프링부트 게시판] 6. yml 설정하기 (0) | 2022.05.01 |
[스프링부트 게시판] 5. lombok 세팅 및 테스트 (0) | 2022.05.01 |
[스프링부트 게시판] 4. http 요청 실습 (0) | 2022.05.01 |