https://lkhlkh23.tistory.com/159

https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/

https://levelup.gitconnected.com/be-careful-with-lombok-2e2edfc01110

https://medium.com/@vgonzalo/dont-use-lombok-672418daa819

롬복

Lombok 은 자바개발자에게서 매우 유명한 프레임워크다. 자바의 기본 메소드들인 getter,setter, equals,hashCode, 생성자들을 만들어준다. 어노테이션 몇개만 채워주게 되면 클래스들의 번거로운 메소드들을 컴파일 시에 자동으로 추가되게 해준다.

하지만, 만약 hibernate Entity 를 사용할 때에는 몇가지 함정에 빠질 수 있다. 이런 함정에 빠지지 않기 위해서는 이런 경우에 Lombok 을 쓰기보단, 여러분이 쓰는 IDE 의 힘을 빌려 메서드들을 구현하는 것이 더 낫다.

@...Constructor 의 함정

롬복은 어노테이션 하나만으로 클래스에 필수적인 생성자를 자동으로 생성해준다.

아래 테스트를 통해, 내가 직접 생성자를 만드는 것과 롬복을 이용해 생성자를 만드는 것에 차이는 없어보인다.

class CoreApplicationTests {

	public static class Member1 {
		private String name;
		private String team;
		private int age;

		public Member1(String name, String team, int age) {
			this.name = name;
			this.team = team;
			this.age = age;
		}
	}
	@AllArgsConstructor
	public static class Member2 {
		private String name;
		private String team;
		private int age;

	}

	// 롬복에 의해 생성자가 생성되었으므로 어떤 예외도 없다
	@Test
	void test() {
		Assertions.assertThatNoException().isThrownBy(()->{
			Member1 member1 = new Member1("11st","CX",27);
			Member2 member2 = new Member2("11st","CX",27);
		});

	}
}

여기서 함정은, 편리하게 생성된 생성자가, 필드의 위치 변화에까지 민감하게 반응한다는 것에 있다.

무슨 말인지 살펴보자.

만약 Member2의 field 순서를 나의 변덕에 의해 바꾼다고 해보자.

	@Getter
	@AllArgsConstructor
	public static class Member2 {
		private String team; //name <-> team 순서 변경
		private String name; 
		private int age;
	}

이런 경우 우리는 생성자의 인자 순서 또한 (name,team,age) 로 바꿔지길 원하진 않을 거다. 만약 그렇다면 위 생성자를 작성한 모든 코드의 파라미터 순서를 바꿔줘야하기 때문이다.

롬복은 시키지 않아도 생성자의 파라미터 순서 또한 바꿔버린다.

class CoreApplicationTests {

	@Getter
	public static class Member1 {
		private String team;
		private String name;
		private int age;

		public Member1(String name, String team, int age) {
			this.name = name;
			this.team = team;
			this.age = age;
		}
	}
	@Getter
	@AllArgsConstructor
	public static class Member2 {
		private String team;
		private String name;
		private int age;
	}

	@Test
	void test() {
		Member1 member1 = new Member1("11st","CX",27);
		Member2 member2 = new Member2("11st","CX",27);
		assertThat(member1.getTeam()).isEqualTo("CX"); // 통과
		assertThat(member2.getTeam()).isEqualTo("CX"); // 실패!
	}
}

아래 테스트는 실패한다. 우리는 member2의 Team 이 "CX"이기를 기대하지만, 롬복에 의해 parameter순서가 뒤바뀌고, 이름과 팀은 타입 또한 문자열로 같기때문에 아무런 문제도 컴파일러는 눈치채지 못한다.