- 연관관계 만들기
@ManyToOne

@OneToMany

@OneToOne

@ManyToMany

(강사님이 ManyToMany는 잘 사용하지 않는다고 하셨습니다.)

자세한 내용은 아래 주소에서 확인하시면 됩니다.

https://getinthere.tistory.com/23?category=884180 

 

스프링부트 with JPA 블로그 8강 - 테이블 생성하기

1. Blog 테이블 만들기 (User, Board, Reply) 2. 연관관계 만들기 @ManyToOne @OneToMany @OneToOne @ManyToMany ManyToMany는 사용하지 않는다. 그 이유는 서로의 primary key로만 중간 테이블을 생성해주는데,..

getinthere.tistory.com

 

 

package com.cos.blog.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cos.blog.model.RoleType;
import com.cos.blog.model.User;
import com.cos.blog.repository.UserRepository;

@RestController
public class DummyControllerTest {
	
	@Autowired // 의존성 주입(DI)
	private UserRepository userRepository;

	// http://localhost:8000/blog/dummy/join (요청)
	// http의 body에 username, password, email 데이터를 가지고 (요청)
	@PostMapping("/dummy/join")
//	public String join(String username, String password, String email) { // key=value (약속된 규칙)
	public String join(User user) { // key=value (약속된 규칙)
//		System.out.println("username: " + username);
//		System.out.println("password: " + password);
//		System.out.println("email: " + email);
		System.out.println("user: " + user);
		System.out.println("username: " + user.getUsername());
		System.out.println("password: " + user.getPassword());
		System.out.println("email: " + user.getEmail());
		
		user.setRole(RoleType.USER);
		userRepository.save(user);
		return "회원가입이 완료되었습니다.";
	}
}

DummyControllerTest를 만들고 join이라는 메서드를 만듭니다.

 

postman을 통해 호출시에 body에 x-www-form-urlencoded 방식으로 요청을 합니다.

이렇게 호출을 하면 join메서드에서 파라미터를 통해 받을 때 각 변수별 String으로 받을수도, User 객체를 통해 받을수도 있습니다.

 

package com.cos.blog.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.cos.blog.model.User;

// DAO
// 자동으로 bean 등록이 된다.
// @Repository // 생략 가능한다.
public interface UserRepository extends JpaRepository<User, Integer> {

}

DB에 Insert하기 위해서는 위와같이 인터페이스를 만들어줘야합니다.

UserRepository 인터페이스에서 JpaRepository를 상속받고 Generic에 User, Integer를 적습니다.

이 말은 해당 JpaRepository는 User Table이 관리하는 Repository이며 Primary Key는 Integer임을 가리킵니다.

JpaRepository 안에는 findAll 등 여러 메소드들을 갖고 있습니다.

회원가입시에는 save를 쓸 예정입니다.

또한 해당 Repository는 자동으로 bean에 등록이 됩니다. 그렇기에 Repository 어노테이션 생략이 가능합니다.

 

DummyControllerTest로 돌아와 해당 Repository를 추가하고 Autowired 어노테이션을 추가합니다.

위에서 사용 된 Autowired 어노테이션은 UserRepository 타입으로 스프링이 관리하는 객체가 있다면 userRepository로 넣어 달라는 의미입니다.

// @autowired 작성 안하고 의존성 주입 방법

@RestController
@RequiredArgsConstructor
public class DummyControllerTest {
	private final UserRepository userRepository;
}

추가로 @RequiredArgsConstructor를 사용하면 final 객체에 대해 생성자를 자동생성하여 생성자 주입을 할 수 있습니다.

 

 

DynamicInsert 어노테이션 : DB insert 과정에서 null인 값에 대해서는 제외처리하는 어노테이션입니다.

<!-- @DynamicInsert 붙이기 전 -->
insert 
    into
        User
        (createDate, email, password, role, username) 
    values
        (?, ?, ?, ?, ?)

<!-- @DynamicInsert 붙인 후 -->
insert 
    into
        User
        (createDate, email, password, username) 
    values
        (?, ?, ?, ?)

 

Enum class 생성으로 넣고자 하는 값을 실수로 넣는 경우를 줄일 수 있습니다.

package com.cos.blog.model;

public enum RoleType {
	USER, ADMIN
}

Enum은 데이터의 도메인을 만들 때 사용합니다. 도메인이라함은 범위라 할 수 있습니다.

 

 

 

강의 주소 : https://youtu.be/w0hF91Xs--4

강의 주소 : https://youtu.be/FhrkWA9hioU

 

JSON은 공용어입니다.

JSON은 중간데이터가 됩니다.

 

 

 

강의 주소 : https://youtu.be/olaeVwjx3J8

연관관계 주인 = FK를 가진 오브젝트

 

SELECT * FROM Board WHERE Id = 1;

한개의 Board를 조회하기 위해서는 Board, User, Reply 객체를 조회해야합니다.

이때 하나의 Board에는 하나의 User와 여러개의 Reply가 존재하게 됩니다.

@ManyToOne(fetch = FetchType.EAGER) // Many = Board, User = One
@JoinColumn(name = "userId")
private User user; //DB는 오브젝트를 저장할 수 없다. FK, 자바는 오브젝트를 저장할 수 있다.

@OneToMany(mappedBy = "board", fetch = FetchType.EAGER) // mappedBy 연관관계의 주인이 아니다 (난 FK가 아니에요) DB에 컬럼을 만들지 마세요.
private List<Reply> reply;

이때 reply는 FK가 아닙니다.

(FK를 설정할때만 JoinColumn 어노테이션이 사용됩니다.)

만약 reply를 FK로 설정하게 되면, 1정규화(원자성)를 어기게 됩니다.

 

mappedBy 속성을 통하여 Reply객체의 board값을 매핑시켜줍니다.

(mappedBy의 의미는 난 연관관계의 주인이 아니며, FK를 만들지 말라는 의미입니다.)

 

 

ManyToOne 어노테이션의 기본 패치 전략은 EAGER입니다.

OneToMany 어노테이션의 기본 패치 전략은 LAZY입니다.

 

바로 보여 줄 필요가 없을때는 LAZY 전략이 맞으나, 바로 보여줘야하는 정보에 대해서는 EAGER전략으로 가야합니다.

(EAGER : 무조건 들고와)

 

 

 

강의 주소 : https://youtu.be/DtMmXQl4_hw

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class Reply {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment
	private int id;
	
	@Column(nullable = false, length = 200)
	private String content;
	
	@ManyToOne
	@JoinColumn(name = "boardId")
	private Board board;
	
	@ManyToOne
	@JoinColumn(name = "userId")
	private User user;
	
	@CreationTimestamp
	private Timestamp createDate;
}

Reply에 대한 테이블을 생성해줍니다.

Entity 어노테이션은 클래스와 가까이 위치하는게 좋습니다.

(이해는 잘 안가지만 강의에서 그렇게 말씀해주셨기때문입니다...)

 

 

강의 주소 : https://youtu.be/u-E9TH4ZaEA

@Entity
public class Board {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY) // auto_increment
	private int id;

	@Column(nullable = false, length = 100)
	private String title;
	
	@Lob // 대용량 데이터
	private String content; // 섬머노트 라이브러리 <html>태그가 섞여서 디자인이 됨.
	
	@ColumnDefault("0")
	private int count; // 조회수
	
	@ManyToOne // Many = Board, User = One
	@JoinColumn(name = "userId")
	private User user; //DB는 오브젝트를 저장할 수 없다. FK, 자바는 오브젝트를 저장할 수 있다.
	
	@CreationTimestamp
	private Timestamp createDate;
}

Board 테이블을 생성합니다.

대용량 데이터에 대해서는 Lob 어노테이션을 선언합니다.

count에서 default값은 int 값이기에 Single quotation은 붙이지 않습니다.

JAVA에서는 ORM방식에 따라 객체를 불러와 Foreign Key를 자동적으로 연결 할 수 있습니다.

이때 JoinColumn을 선언하여 해당 Column의 이름을 userId로 지칭합니다.

또한 ManyToOne 어노테이션을 통해 여러개의 Board에 대해 하나의 사용자만 접근 할 수 있음을 정해줍니다.

 

강의 주소 : https://youtu.be/MJSMvETSE7E

DB 인코딩 타입 문제로 인해 변경하는 강의입니다.

 

 

강의 주소 : https://youtu.be/s1AxIA033jQ

package com.cos.blog.model;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;

@Entity // User 클래스가 MySQL에 테이블이 생성이 된다.
public class User {
	
	@Id //Primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY) // 프로젝트에서 연결된 DB의 넘버링 전략을 따라간다.
	private int id; // 시퀀스, auto_increment
	
	@Column(nullable = false, length = 30)
	private String username;
	
	@Column(nullable = false, length = 100) // 123456 => 해쉬(비밀번호 암호화)
	private String password;
	
	@Column(nullable = false, length = 50)
	private String  email;
	
	@ColumnDefault("'user'") // 문자라는 것을 알려주기 위해 싱글쿼테이션을 넣는다.
	private String role; // Enum을 쓰는게 좋다. // admin, user, manager
	
	@CreationTimestamp // 시간이 자동 입력
	private Timestamp createDate;
}

 

Enum 타입은 데이터를 도메인으로 설정 할 수 있습니다.

 

jpa:
    open-in-view: true
    hibernate:
      ddl-auto: create
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
      use-new-id-generator-mappings: false
    show-sql: true
    properties:
      hibernate.format_sql: true

ddl-auto : create -> 생성하고자 하는 테이블이 기존에 있어도 새로 만듭니다( 추후에는 update로 변경해야합니다.)

use-new-id-generator-mappings : JPA가 사용하는 기본 넘버링 전략을 선택 할 수 있습니다.

 

아래 두 속성값은 spring boot를 실행시 콘솔에 쿼리를 보여주며, 깔끔하게 정리하여 보여준다는 의미입니다.

show-sql: true
    properties:
      hibernate.format_sql: true

physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

: Entity 생성시 기입 된 내용대로 컬럼을 생성해 줍니다.

private String myEmail; // myEmail

 

physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

: Entity 생성시 언더스코어로 컬럼을 생성해 줍니다.

private String myEmail; // my_email

 

위에 대한 자세한 설명은 아래의 주소를 참고해주세요.

https://getinthere.tistory.com/20

 

스프링부트 with JPA 블로그 6강 - yaml 설정

1. yaml 이란 이 분이 설명을 너무 잘해두셔서 ㄷㄷ https://www.inflearn.com/questions/16184 yaml파일 이란 무엇인가요 - 인프런 질문 - yaml파일 이란 무엇인가요 안녕하세요 강사님 너무 질문이 많아서 죄송.

getinthere.tistory.com

 

 

강의 주소 : https://youtu.be/6ynr-XAI-rk

1. yaml이란?

    - 정리가 잘 된 주소 참조합니다.

https://www.inflearn.com/questions/16184

 

yaml파일 이란 무엇인가요 - 인프런 | 질문 & 답변

안녕하세요 강사님 너무 질문이 많아서 죄송합니다. yaml파일 이라는 단어를 요 근래 많이 듣고 있는데 정확인 무슨 파일인가요 검색해 보지도 않고 무조건 질문을 드리는것 같아서 죄송하지만

www.inflearn.com

 

server:
  port: 8000
  servlet:
    context-path: /blog

port는 8000이며, context-paht는 /blog입니다.

 

RestController 어노테이션은 문자 그대로를 return하는 반면,

Controller 어노테이션을 이용하게되면, file을 return하게 됩니다.

@Controller
public class TempControllerTest {

	// http://localhost:8000/blog/temp/home
	@GetMapping("/temp/home")
	public String tempHome() {
		System.out.println("tempHome()");
		// 파일리턴 기본경로 : src/main/resources/static
		// 리턴명 : /home.html
		// 풀경로 : src/main/resources/static/home.html
		return "/home.html";
	}
}

스프링 부트의 경우는 JSP파일을 인식하지 못합니다.

그래서, JSP 템플릿 엔진을 pom.xml에 추가해줘야합니다.

<!-- JSP 템플릿 엔진 -->
<dependency>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

또한 JSP파일은 정적 파일이 아니기 때문에, 위의 파일 리턴 기본 경로인 static 하위에 위치하여도 JSP파일은 읽히지 않습니다. 이유는 static하위에는 브라우저가 인식 할 수 있는 정적 파일만 있어야합니다.

	@GetMapping("/temp/jsp")
	public String tempJsp() {
		return "/test.jsp";
	}

이를 위해, src/main/webapp/WEB-INF/views라는 폴더를 생성하고,

application.yml에 아래와 같이 추가합니다.

spring:
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp

또한 해당 jsp를 호출할때 메소드에서의 호출 방법은 아래와 같습니다.

	@GetMapping("/temp/jsp")
	public String tempJsp() {
		// prefix : /WEB-INF/views/
		// suffix : .jsp
		// 풀네임 : /WEB-INF/views/test.jsp
		
		return "test";
	}

 

static 하위의 파일에 접근하던것과 다르게 prefix, suffix가 존재하여 return시에 return하고자하는 파일명만 집어 넣으면 됩니다.

 

 

 

강의 주소 : https://youtu.be/U9OnYKiSf4g

 

롬복 설치 과정은 아래 강의를 참조하겠습니다.

 

@Getter
@Setter
public class Member {

	private int id;
	private String username;
	private String password;
	private String email;
	
}
@Data
public class Member {

	private int id;
	private String username;
	private String password;
	private String email;
	
}

위 두개의 내용은 서로 같은 내용입니다.

@Getter, @Setter를 두개 다 쓰고 싶다면 @Data라는 어노테이션을 쓰면 됩니다.

 

@NoArgsConstructor : 빈 생성자를 추가하는 어노테이션입니다.

@AllArgsConstructor : 전체 생성자를 추가하는 어노테이션입니다.

@RequiredArgsConstructor : final이 붙은 변수에 대해 생성자를 추가하는 어노테이션입니다.

package com.cos.blog.test;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member {
	private int id;
	private String username;
	private String password;
	private String email;
}

 

@Builder : 해당 어노테이션 선언시 객체를 선언할때 아래와 같은 방식으로 선언하여 사용 할 수 있습니다.

    - builder의 장점

      1. 생성자의 순서를 지키지 않아도 됩니다.

      2. 필드의 값이 무엇이었는지 생각하지 않아도 됩니다.

Member m = Member.builder().username("ssar").password("1234").email("ssar@nate.com").build();
package com.cos.blog.test;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class Member {
	private int id;
	private String username;
	private String password;
	private String email;
	
	@Builder
	public Member(int id, String username, String password, String email) {
		this.id = id;
		this.username = username;
		this.password = password;
		this.email = email;
	}
}
@GetMapping("/http/lombok")
public String lombokTest() {
    Member m = Member.builder().username("ssar").password("1234").email("ssar@nate.com").build();
    System.out.println(TAG+"getter:"+m.getUsername());
    m.setUsername("cos");
    System.out.println(TAG+"setter:"+m.getUsername());
    return "lombok test 완료";
}
HttpController : getter:ssar
HttpController : setter:cos

 

 

강의 주소 : https://youtu.be/U3Bq4C-NEDU

 

MAVEN : 프로젝트 관리 툴입니다.

프로젝트 시작시 pom.xml 파일을 읽어들여 .m2 폴더에 필요한 라이브러리들을 다운로드 받아 빌드까지 해줍니다.

 

 

강의 주소 : https://youtu.be/jtur8oAAXYg

+ Recent posts