백엔드

[Spring JPA] Entity에 setter대신 생성자 활용하기

콩지연 2023. 7. 10. 09:09

[Entity에 setter대신 생성자 활용하기]

 

목표

setter대신 생성자 활용해보기

 

 

setter을 사용하지 말아야 하는 이유

1. 사용자의 의도를 파악하기 어렵다.

Member member = new Member();
member.setUsername("name1");
member.setAge(25);
member.setTeam(teamA);

위의 코드를 보면 새로운 member객체를 생성하는 것인지, 값을 변경하는 것인지 의도를 파악하기 어렵다. 

이 코드는 새로운 member객체를 생성하는 것지만, 객체의 요소가 많아질수록 더욱 복잡해질 것이다.

 

Member member = new Member("name1", 25, teamA);

위의 코드 또한 member객체를 생성하는 것으로, 생성자를 이용해 setter를 활용하는 것보다 코드를 이해하기 쉽다.

 

 

2. 일관성을 유지하기 어렵다.

Member member = em.find(Member.class, 1L);
member.setUsername("name1");
member.setAge(25);
member.setTeam(teamA);

객체 값 변경을 위해 public으로 작성된 setter을 사용하면, 어디서든 접근 가능하므로 의도치 않게 값이 변경될 수 있다.

그리고 값이 변경된다면 어디서 변경되었는지 찾기 어렵다. 이렇게 setter을 사용하게 되면 일관성을 유지하기 어렵다.

 

 

setter대신 객체 생성, 수정하는 방법

1. 생성자를 사용하기

public class Member {

    @Id @GeneratedValue
    private Long id;

    private String username;

    private int age;

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

    //생성자 활용하기
    public Member(String username, int age, Team team) {
        this.username = username;
        this.age=age;
        if(team !=null) changeTeam(team);
    }
}

위의 코드를 보면 생성자 메서드를 이용해 Member객체에 username과 age, team의 값을 초기화 할 수 있다.

객체를 생성할 때는 setter로 각자의 값을 초기화하기 보다 생성자를 이용하자!

 

 

2. 연관관계 메서드 활용하기

public void changeTeam(Team team){
     if(this.team!=null) this.team.getMembers().remove(this);    //기존의 team에 member객체 지우기
     this.team = team;
     team.getMembers().add(this);                               //새로운 team에 member객체 넣기
}

위 코드를 보면 Member객체의 변수인 team을 변경하기 위해 changeTeam메서드를 만들었다.

만약 team이 null이 아니라면 현재 member가 team을 가지고 있는 것이므로 team리스트에서 제거했다.

그리고 현재 this.team을 바꿀 값인 team으로 변경시키고, 변경될 team리스트에 member객체를 더해주었다.

 

 

+) 클래스 Team 코드

public class Team {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

    //==생성자==//
    public Team(String name){
        this.name=name;
    }
}

 

 

Test 해보기

1. 코드 작성

class MemberTest {

    @PersistenceContext
    EntityManager em;

    @Test
    public void testEntity(){
        
        //team객체 생성
        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");

        em.persist(teamA);
        em.persist(teamB);
        
        //member 객체 생성
        Member member1 = new Member("member1", 10, teamA);
        Member member2 = new Member("member2", 20, teamB);
        Member member3 = new Member("member3", 30, teamA);
        Member member4 = new Member("member4", 40, teamB);

        em.persist(member1);
        em.persist(member2);
        em.persist(member3);
        em.persist(member4);
        
        //member1의 team을 바꾸기
        member1.changeTeam(teamB);

        //teamA와 teamB의 멤버 구성 출력하기
        System.out.println("teamA : " +teamA.getMembers());
        System.out.println("teamB : " +teamB.getMembers());

    }
}

위의 코드를 보면 team객체를 2개 생성하고, member객체를 4개 생성했다.

그 후 changeTeam메서드를 활용해 username이 member1인 객체의 team을 teamA에서 teamB로 바꾸었다.

 

 

2. 결과

결과를 보면 teamA에서 member1이 사라지고, member1은 teamB에 속해있는 것을알 수 있다.