클래스 다이어그램을 보며 엔티티를 만들겠습니다.

1. league 패키지 밑에 domain 패키지를 만들어줍니다.

2. User 객체를 만들고 아래와 같이 작성해줍니다. 

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Long id;

    @Column(name = "email")
    private String email;

    @Column(name = "password")
    private String password;

    @Column(name = "user_name")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
    private League league;

    @OneToMany(mappedBy = "user")
    private List<RequestTeam> requestTeamList =new ArrayList<>();

    @Enumerated(EnumType.STRING)
    private ROLE role;

    @Embedded
    private Address address;

    // 연관 관계 메소드
    public void setTeam(Team team){
        this.team=team;
    }
    public void setLeague(League league){
        this.league=league;
    }

    
    // 생성 메소드
    public static User createUser(String email, String password, String name, Address address, ROLE role){
        User user = new User();
        user.email=email;
        user.role=role;
        user.password=password;
        user.address=address;
        user.name=name;
        return user;
    }
}

 

 

@xxxToOne으로 끝나는 맵핑들은 fetch = FetchType.LAZY로 설정해줍니다. 그 이유는 EAGER를 사용할 경우 연관된 객체를 모두 한번에 가져오기 때문에 개발자가 원하지 않는 Query가 DB에 날라갈 수 있습니다. 반면에 LAZY는 연관된 객체를 Proxy로 찾아오고 Proxy객체를 직접 사용할 때 Query가 DB에 날라갑니다.

 

@JoinColumn: name 속성은 table에서 Fk의 이름을 정하는 역할을 합니다.

 

@Enumerated: enum을 사용한다는 뜻입니다. 속성은 String으로 줍니다. Original로 줄 시 enum의 필드 순서대로 0, 1, 2... 지정됩니다. 이때 새로운 필드가 생길 시 전체 지정된 숫자를 변경해야 하므로 유지보수에 어려움이 있습니다.

 

@Embedded: Entity는 아니지만 객체이며 단순한 값타입으로 사용하는 객체에 붙여주는 어노테이션 입니다.

 

연관 관계 메소드들은 Entity들 사이에서의 관계를 지정해주기 위해 사용합니다. 사용하기 편하신 쪽에서 연관 관계 메소드를 만들어 사용하시면 됩니다. 

 

Entity는 영속성 컨테스트에서 관리될 객체이기 때문에 무분별한 생성을 막기위해 @NoArgsConstruct를 이용하여 default 생성자를 막아둡니다. createUser 생성 메소드를 통해서만 User를 생성할 수 있습니다.

현재 다른 Entity들은 생성하지 않아 오류가 뜨는 게 정상입니다. 


2. Team

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Team extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "team_id")
    private Long id;

    @Column(name = "team_name")
    private String name;

    @Column(name = "team_max_size")
    private Integer maxSize;

    @Column(name = "founder_email")
    private String email;

    @Column(name = "team_now_size")
    private Integer nowSize;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "league_id")
    private League league;

    @OneToMany(mappedBy = "team")
    private List<RequestTeam> requestTeamList = new ArrayList<>();

    @OneToMany(mappedBy = "team")
    private List<RequestLeague> requestLeagueList = new ArrayList<>();

    @OneToMany(mappedBy = "team")
    private List<User> userList = new ArrayList<>();



	// 연관 관계 메소드
    public void setUser(User user){
        user.setTeam(this);
    }
    public void addTeam(User user){
        userList.add(user);
    }

    public void setLeague(League league){
        this.league=league;
    }


	// 생성 메소드
    public static Team createTeam(User user,String name, Integer maxSize){
        Team team = new Team();
        team.name=name;
        team.maxSize=maxSize;
        team.email=user.getEmail();
        team.nowSize=0;
        team.addTeam(user);
        team.setUser(user);
        return team;
    }
}

 

3. RequestTeam

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RequestTeam extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "request_team_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    @Column(name = "request_team")
    private Boolean request;


    private void setUser(User user) {
        this.user=user;
    }

    private void setTeam(Team team){
        this.team=team;
    }

	// 연관 관계 메소드
    private void addRequestTeam(){
        user.getRequestTeamList().add(this);
        team.getRequestTeamList().add(this);
    }

	// 생성 메소드
    public static RequestTeam createRequestTeam(User user, Team team){
        RequestTeam requestTeam = new RequestTeam();
        requestTeam.request=false;
        requestTeam.setTeam(team);
        requestTeam.setUser(user);
        requestTeam.addRequestTeam();
        return requestTeam;
    }
}

4. League

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class League {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "league_id")
    private Long id;

    @Column(name="league_name")
    private String leagueName;

    @Column(name = "league_scale_size")
    private Integer scaleSize;

    @Column(name= "league_now_size")
    private Integer nowSize;

    @Column(name = "league_host_name")
    private String email;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @OneToMany(mappedBy = "league")
    private List<RequestLeague> requestLeagueList = new ArrayList<>();

    @OneToMany(mappedBy = "league")
    private List<Team> teamList = new ArrayList<>();

	
    // 연관 관계 메소드
    private void setUser(User user){
        this.user=user;
    }

    private void setLeague(){
        user.setLeague(this);
    }

    public void addTeam(Team team){
        teamList.add(team);
    }

    public void setLeague(Team team){
        team.setLeague(this);
    }

	// 생성 메소드
    public static League createLeague(Integer scaleSize,String leagueName, User user){
        League league = new League();
        league.leagueName=leagueName;
        league.scaleSize=scaleSize;
        league.nowSize=0;
        league.email=user.getEmail();
        league.setUser(user);
        league.setLeague();
        return league;
    }
}

5. RequestLeague

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class RequestLeague extends BaseEntity {
    @Id
    @GeneratedValue
    @Column(name = "request_league_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "league_id")
    private League league;

    @Column(name = "request_league")
    private Boolean request;

    private void setLeague(League league){
        this.league=league;
    }
    private void setTeam(Team team){
        this.team=team;
    }
	
    // 연관 관계 메소드
    private void addRequestLeague(){
        this.team.getRequestLeagueList().add(this);
        this.league.getRequestLeagueList().add(this);
    }

	// 생성 메소드
    public static RequestLeague createRequestLeague(Team team, League league){
        RequestLeague requestLeague = new RequestLeague();
        requestLeague.request=false;
        requestLeague.setLeague(league);
        requestLeague.setTeam(team);
        requestLeague.addRequestLeague();
        return requestLeague;
    }
}

6. BaseEntity

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public class BaseEntity {

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdTime;

    @LastModifiedDate
    private LocalDateTime lastChangedTime;

    @Column(updatable = false)
    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String lastModifiedBy;
}

@MappedSuperclass: 공통된 정보를 Entity에서 필요로할 때 상속으로 필드를 사용 가능하게 합니다. 엔티티가 생성, 변경되는 시간 변경, 만든 사람을 공통 필드로 사용할 수 있게 됩니다.

 

@SpringBootApplication
@EnableJpaAuditing
public class BlogProjectApplication {

    public static void main(String[] args) {
        SpringApplication.run(BlogProjectApplication.class, args);
    }

    @Bean
    public AuditorAware<String> auditorAware(){
        return () -> Optional.of(UUID.randomUUID().toString());
    }

}

 

Auditing을 사용하기 위해서 Application에 @EnableJpaAuditing을 선언해주고, 만드는 사람의 식별자를 사용하기 위해 @Bean을 등록해줍니다.

 

7. Address

@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Address {

    private String city;
    private String street;

	// 생성 메소드
    @Builder
    public Address(String city, String street){
        this.city=city;
        this.street=street;
    }
}

 

8. ROLE

@Getter
@RequiredArgsConstructor
public enum ROLE {
    MEMBER,
    TEAM_FOUNDER,
    LEAGUE_HOST
}

 

User의 역할을 구분 하기 위한 Enum입니다.

 

 

JPA의 자세한 개념은 아래 링크들에서 확인부탁드리겠습니다:)

https://dingdingmin-back-end-developer.tistory.com/entry/Spring-data-JPA2-%EA%B0%9C%EB%85%90-%EB%81%9D

 

Spring-data-JPA(2) 개념 [끝]

연관 관계 단반향 연관관계 @Entity public class User{ @Id @GeneratedValue private Long id; @Column private String name; @Column private int age; @ManyToOne @JoinColumn(name= "team_id") private Team t..

dingdingmin-back-end-developer.tistory.com

https://dingdingmin-back-end-developer.tistory.com/entry/Spring-data-JPA1-%EC%97%94%ED%8B%B0%ED%8B%B0-Entity

 

Spring-data-JPA(1) [엔티티] Entity

@Entity JPA가 괸리하는 엔티티라는 어노테이션이다. 기본 생성자가 필수이다. (파라미터가 없는 protected 생성자 ) final 클래스, enum, interface 사용 불가 저장할 필드에 final 사용 X 속성 name --> JPA에서..

dingdingmin-back-end-developer.tistory.com

 

완성된 패키지 형태입니다. 

 

다음은 각 객체들의 Repository와 Service를 만들고 Test까지 진행하겠습니다. 감사합니다.

모든 코드는 아래 링크에서 확인 가능합니다.

https://github.com/rlaehdals/blogProject

 

GitHub - rlaehdals/blogProject

Contribute to rlaehdals/blogProject development by creating an account on GitHub.

github.com