TIL - 2022

TIL 20220721 (@Transactional, Hikari CP, @Embeddable, mappedBy 연관관계 )

바랄 희 2022. 7. 23. 02:13

@Transactional

트랜잭션 처리를 지원하는 어노테이션

 

트랜잭션은 모든 작업이 성공적으로 이루어져야 결과를 적용하고, 오류가 어떤 부분에서 발생한 경우에는 이전의 작업들을 모두 되돌리고 반영하지 않는 것

 

@Transactional
    public void createItem(ItemRequestDto ItemRequestDto){
        try {
            Item item = Item.builder()
                    .name(ItemDto.getname())
                    .deposit(ItemDto.getdeposit())
                    .rentalFee(ItemDto.getrentalFee())
                    .build();

            ItemRepository.save(item);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

 

위와 같은 코드에서는 요청이 들어온 데이터를 저장하기 전에 유효성 검사를 통해서 검사를 한 뒤에 저장을 할 수 있도록 했다. 만약 유효성 검사에 통과하지 못하면, 이전으로 모든 작업들을 되돌리고 오류를 뱉도록 하는 것이다.

 

해당 어노테이션은 테스트 환경에서도 사용된다.

서비스 레이어에 대하여 테스트를 하게 되면 DB에 영향을 미치게 되고, 테스트임에도 이가 남아있는 경우 추후 실제 서비스에 영향을 미칠 수 있기 때문에 테스트가 끝나면 이를 모두 지워야 하기 때문이다. 

 

HIkari CP

개발 중에 위와 같은 오류를 마주한 적이 있다. 사실은 정~말 쓸데없는 오류이긴 했는데 (내가 properties 에 db 설정을 제대로 안해두어서 그런 거였다..) 이 과정에서 Hikari cp 를 처음 봐서 기록해야겠다고 생각했다.

 

아래의 링크를 참고했다.

 

https://brunch.co.kr/@jehovah/24

 

HikariCP 뜯어보기 1편

너는 Connection Pool을 대체 어떻게 관리하니? | HikariCp가 그렇게 좋다면서요...? 저는 자바 개발자가 아니라서 HikariCp가 도대체 뭔지 몰랐습니다. 회사에 입사하고 보니 HikariCP에 대한 내용이 스물스

brunch.co.kr

 

Hikari CP의 역할

데이터베이스와의 커넥션 풀을 관리해주는 역할을 한다.

HikariCP를 이용하면, 미리 정해놓은 만큼의 커넥션을 풀에 담아놓고 요청이 들어오면 Thread 가 커넥션을 요청하면 HikariCP는 풀에 있는 커넥션을 연결해준다. 따라서 Thread 입장에서는 쿼리를 바로 날릴 수 있게 되는 것이다.

 

Hikari CP는 'org.springframework.boot:spring-boot-starter-jdbc  에 포함되어 있기 때문에 굳이 빠로 추가할 필요는 없다.

 

application.yml 파일에서 jdbc에 대한 설정을 해줄 때 hikariCP가 유지관리하는 최소 유휴 연결 수를 설정하기도 한다.

 

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/world?serverTimeZone=UTC&CharacterEncoding=UTF-8
    username: root
    password: your_password
    hikari:
      maximum-pool-size: 10
      connection-timeout: 5000
      connection-init-sql: SELECT 1
      validation-timeout: 2000
      minimum-idle: 10
      idle-timeout: 600000
      max-lifetime: 1800000

server:
  port: 8000

 

mysql - springboot 연결

이전에 스프링부트 강의를 들을 때에는 h2 를 이용해서 데이터가 제대로 들어갔는지 확인을 했었다. 그러나 h2는 실무에서 잘 쓰지도 않는다고 알고 있고, 강의자분도 강의 이후에는 다른 데이터베이스로 바꿔서 사용해보라고 하셔서 mysql 로 연결해봤다!

 

https://computer-science-student.tistory.com/405

 

[스프링 부트, Spring Boot] MySQL 연동

Spring Boot MySQL 연동 gradle을 사용할 때, src/main/resources/application.properties에 들어가서 아래 내용을 넣어주면 된다. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasou..

computer-science-student.tistory.com

https://limjunho.github.io/2021/08/11/spring-mysql.html

 

Spring boot mysql 연동(mybatis) - limjunho

Summry 본 문서에서는 Spring Boot 프로젝트에서 MyBatis Framework를 이용한 MySQL 연동 방법을 정리한다. 본 문서에서 제공하는 예시는 portfolio 테이블의 내용을 get request를 통해 확인해보는 코드이다. 본

limjunho.github.io

 

이 두 링크를 참고해서 했고, workbench도 깔아서 데이터베이스 연결에 성공했다.

 

@Embeddable

이는 밸류 클래스라고 한다.

밸류 클래스는 내장된 클래스와 같이 (int, double, String) 하나의 값을 나타내는 클래스.

보통 주소를 저장하기 위해서는 분리해서 저장을 한다. (지자체명, 도로명, 상세주소 와 같이)

합쳐져야 정확한 의미를 갖는데도 변수를 분리해서 저장하게 되면 비효율적으로 코드를 짜게 되기 때문에 사용하게 된다.

 

아래는 변수를 분리해서 저장하는 경우이다.

String address1 = "서울시 강동구 천호동";
String address2 = "개발아파트 110동 1101";
String zipCode = "192-32";

 

아래는 밸류 클래스를 사용한 경우이다.

 

컬럼을 하나의 객체로 사용하고 싶다면, @Embeddable, @Embedded를 사용하면 된다. 

@Embeddable
class Address {    
			String address1;    
			String address2;    
            	String zipCode;
            }

 

@Entity
@Table(name="order")

public class Order{

		@Id
        @GeneratedValue
        private Long id;
        
        private String name;
        
        @Embedded
        private Adress adress;
        
			
           }

 

Entity 클래스에서 객체 필드를 생성하고 그 위에 Embedded 어노테이션을 사용하면 된다.

 

이렇게 엔티티를 작성하면, Adress 객체에 존재하는 adress1, adress2, zipcode 전부가 Order 엔티티의 필드로 들어가게 된다.

 

mappedBy

 

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;
    
    private String memberName;
    
    @ManyToOne
    @JoinColumn("team_id")
    private Team team;
}

@Entity
public class Team {
    @Id @GeneratedValue
    private Long id;
    
    private String teamName;
    
    @OneToMany(mappedBy = "team")
    List<Member> members = new ArrayList<>();
}

1:N Team:Member

 

Member 입장에서는 멤버가 many 이고 팀이 one 이므로 @ManyToOne 어노테이션을 사용하며, member 테이블에 team 객체는 team_id 라는 필드명으로 저장될 수 있도록 한다.

 

Team 입장에서는 팀이 one이고 멤버가 many 이므로 @OneToMany 어노테이션을 사용하며 mappedBy 를 이용하여 연관관계에서 Team이 주인이 아닌 것을 표시한다. mappeBy의 값은 반대쪽에서 자신이 매핑되어있는 필드명을 쓰면 된다.

 

연관관계의 주인이 아닌, 즉 mappedBy가 정의된 클래스에서는 값을 변경하거나 등록할 수 없으며 읽는 것만 가능하다.

 

N 즉 ManyToOne 어노테이션을 사용하는 클래스가 연관관계의 주인으로 선정되며 연관관계의 주인은 fk 를 갖고 있다.