Controller,Service
https://brio-sw.tistory.com/36
컨트롤러에 비즈니스 로직을 둘 수는 있지만, 이는 컨트롤러가 너무 많은 역할을 담당하게 된다.
그래서 비즈니스 로직을 Service 서비스 계층을 별도로 생성하여 처리한다.
그리고 Controller 컨트롤러는 비즈니스 로직이 있는 서비스를 호출하는 역할을 담당한다.
비즈니스 로직을 변경하면 비즈니스 로직을 호출하는 컨트롤러의 코드도 함께 변경될 수 있다.
mvc패턴
mvc+frontconroller 2개의 패턴이 합쳐져서
현재의 mvc패턴이 만들어졌다
- DispatcherServlet(Front Controller)
: 제일 앞단에서 HTTP Request를 처리하는 컨트롤러 - Controller(Handler)
: HTTP Request를 처리해 Model을 만들고 View 지정 - ModelAndView
: Controller에 의해 반환된 Model과 View가 Wrapping 된 객체
(Model은 데이터만 저장하고 ModelAndView는 데이터와 이동하고자 하는 view page를 함께 저장한다.) - ViewResolver
: ModelAndView를 처리해 View 그리기
동작 순서
- 핸들러 조회
- 핸들러 어댑터 조회
- 핸들러 어댑터 실행
- 핸들러 실행
- ModelAndView 반환
- viewResolver 호출
- View 반환
- 뷰 렌더링
@RequestMapping
요청 정보를 매핑하는 어노테이션으로 해당 URL이 호출되면 해당 메소드가 실행된다.
- @GetMapping
- @PostMapping
출처 : https://velog.io/@dbsrud9126/Spring-MVC
Repository
리포지터리는 엔티티에 의해 생성된 데이터베이스 테이블에 접근하는 메서드들(예: findAll, save 등)을 사용하기 위한 인터페이스이다. 데이터 처리를 위해서는 테이블에 어떤 값을 넣거나 값을 조회하는 등의 CRUD(Create, Read, Update, Delete)가 필요하다. 이 때 이러한 CRUD를 어떻게 처리할지 정의하는 계층이 바로 리포지터리이다.
JPA
ORM이란?
https://brio-sw.tistory.com/28
Entity란?
PK설정방법,@Entity사용방법,기본생성
- @GenerateValue(strategy = GenerateType.IDENTITY)란?
- @Entity 사용방법
- 기본 생성자 필수
https://brio-sw.tistory.com/54#%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%99%84%EB%A3%8C-1
영속성 컨텍스트, JPA-update?
https://brio-sw.tistory.com/28
Transaction과 AOP
생각의 흐름->
- Transactionan의 원자성을 보장해주기 위한 코드가 비즈니스 로직과 함께 존재합니다. 따라서, 개발자는 핵심 비지니스 로직에 집중할 수 없습니다.
- Transaction에 관한 connection 관련 코드와 try~catch 코드가 중복 된다.
Transaction을 처리해주어야 하는 곳이 여러 곳이라면 해당 try~catch를 반복적으로 작성해줘야 합니다. - 여기서 생각할 수 있는 개념이 AOP(Aspect Oriented Programming)로, 관점 지향 프로그래밍이라는 뜻입니다.
AOP
이체, 입출금, 이자 계산이라는 기능이 있습니다. 세 기능은 로깅, 트랜잭션, 보안에 대한 처리를 해주어야합니다.
비즈니스 로직을 제외하고 공통적으로 가지는 부가 기능을 따로 분리하여 관리하는 것이 관점 지향 프로그래밍입니다.
Spring에서 사용하는 @Transactional 어노테이션도 AOP의 개념이 적용된 것 입니다.
트랜잭션을 적용해야 하는 메서드 혹은 클래스에 @Transactional 어노테이션만 작성해주면 됩니다.
@Service
public class PostService {
@Transactional
public Long addPost(Long boardId, NewPostRequest newPostRequest, AuthInfo authInfo) {
// 새로운 게시글을 등록하는 비즈니스 로직만을 작성
}
@Transactional
public void updatePost(Long postId, PostUpdateRequest postUpdateRequest, AuthInfo authInfo) {
// 게시글을 수정하는 비즈니스 로직만을 작성
}
Spring의 Transaction 동작 방식에 대한 기본 개념
Spring에서는 @Transactional 어노테이션을 통해서 쉽고 깔끔하게 트랜잭션 처리를 해줄 수 있습니다.
하지만, 위 어노테이션이 어떻게 동작함으로써 트랜잭션을 보장해주는지 궁금합니다.
Proxy
스프링은 기본적으로 트랜잭션을 Proxy를 통해서 처리합니다.
실제로 PostService의 addPost 메서드를 요청하면, 동작 전의 코드로는 위와 같이 보입니다.
하지만, 실제로 런타임에는 아래와 같이 동작합니다.
스프링이 어플리케이션이 동작할 때, Transaction 전후 처리를 하는 Proxy를 동적으로 생성해줍니다.
@Transaction이 선언된 Class(Target)에 대해 Target을 참조하는 Proxy를 스프링이 생성합니다. Target의 트랜잭션 처리가 필요한 요청은 Proxy에게 요청되고 Proxy가 Transaction 전후 처리를 하는 방식입니다.
spring data jpa
jpa VS spring data jpa
JPA는 Java에서 객체-관계 매핑을 위한 표준 명세로 인터페이스 입니다.
자바 애플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스와
어노테이션의 표준 집합을 정의합니다.
-Entity Manager
Spring Data JPA는 JPA 기반 애플리케이션 개발을 보다 쉽게 만들기 위해
JPA 위에 추가적인 기능과 추상화를 제공하는 라이브러리/프레임워크입니다
-Repository interface
+)여기서 주목할 부분은 JPA는 특정 기능을 하는 라이브러리가 아닌 인터페이스라는 점입니다.
자바 어플리케이션에서 관계형 데이터베이스를 어떻게 사용해야 하는지를 정의하는 한 방법일 뿐이고 단순한 명세이기에 구현은 없고, 다양한 ORM 프레임워크(예: Hibernate, EclipseLink, OpenJPA 등)에서 구현할 수 있는 공통 API를 제공합니다.
why spring data jpa?
DB에 접근할 필요가 있는 대부분의 상황에서는 Repository를 정의하여 사용하기 때문입니다
이 Repository가 바로 Spring Data JPA의 핵심입니다.
사용자가 Repository 인터페이스에 정해진 규칙대로 메서드를 입력하면, Spring이 알아서 해당 메서드 이름에 적합한 쿼리를 날리는 구현체를 만들어서 Bean으로 등록해 줍니다.
CRUD 연산, 페이징, 정렬과 같은 JPA 리포지토리를 구현하는 데 필요한 반복적인 코드 양을 줄이는 인터페이스와 클래스를 제공합니다.
사용방법 및 출처 :
https://lealea.tistory.com/238
연관관계 매핑
단방향 연관관계:
단방향 연관관계는 한 객체가 다른 객체를 참조할 수 있지만, 참조된 객체가 다시 이를 역으로 참조할 수 없는 관계입니다.
1:N 참조에서 나타난다
// 예시: 부서(Department)가 여러 직원(Employee)을 가질 수 있지만,
// 직원은 부서를 알 수 없는 단방향 연관관계
public class Department {
private List<Employee> employees;
// getter, setter 생략
}
public class Employee {
// 부서 정보는 여기서 알 수 없음
}
양방향 매핑:
양방향 매핑은 두 객체 간의 상호 관계를 표현하는 것입니다. 한 객체가 다른 객체를 참조하면서, 그 반대의 관계도 마찬가지로 설정됩니다.
// 예시: 양방향 연관관계
public class Department {
private List<Employee> employees;
// getter, setter 생략
}
public class Employee {
private Department department;
// getter, setter 생략
}
연관관계에서의 주인 : mappedBy로 사용된다
orm을 사용할때 주인은 데이터베이스의 테이블에 변경을 가할 때 관계를 관리합니다
즉, 주인의 객체는 db테이블에 바로 반영되지만 주인이 아닌 객체는 단순히 참조하는 용도로만 사용되며 db에 영향을 주지 않는
// 학생(Student) 클래스
import java.util.List;
import javax.persistence.*;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "student")
private List<Enrollment> enrollments;
// Getter와 Setter, 생성자 생략
}
// 과목(Subject) 클래스
import java.util.List;
import javax.persistence.*;
@Entity
public class Subject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "subject")
private List<Enrollment> enrollments;
// Getter와 Setter, 생성자 생략
}
// 수강(Enrollment) 클래스 (중간 테이블 역할)
import javax.persistence.*;
@Entity
public class Enrollment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "student_id")
private Student student;
@ManyToOne
@JoinColumn(name = "subject_id")
private Subject subject;
// Getter와 Setter, 생성자 생략
}
N:M 양방향 매핑이 필요할 때 해결방법:
중간 테이블을 추가하여 1:N 관계로 나누어 해결할 수 있습니다.
예를 들어, 학생과 과목 간의 다대다 관계를 고려해보겠습니다.
하나의 학생은 여러 과목을 수강할 수 있고, 한 과목에는 여러 학생이 수강할 수 있습니다.
이를 1:N 관계로 나누어 해결할 수 있습니다.
// 학생(Student) 클래스
import java.util.List;
import javax.persistence.*;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "student")
private List<Enrollment> enrollments;
// Getter와 Setter, 생성자 생략
}
// 과목(Subject) 클래스
import java.util.List;
import javax.persistence.*;
@Entity
public class Subject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "subject")
private List<Enrollment> enrollments;
// Getter와 Setter, 생성자 생략
}
// 수강(Enrollment) 클래스 (중간 테이블 역할)
import javax.persistence.*;
@Entity
public class Enrollment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "student_id")
private Student student;
@ManyToOne
@JoinColumn(name = "subject_id")
private Subject subject;
// Getter와 Setter, 생성자 생략
}
'SpringBoot' 카테고리의 다른 글
스프링 데브툴 설정 (0) | 2024.05.11 |
---|---|
IOC,DI,BEAN,LOMBOK (0) | 2024.04.09 |