💬 모델을 왜 이렇게 복잡하게 구현해야 하나요? ㅠㅠ
➡️ 변경에 자유롭게 만들기 위해! (유지보수)
기술 별로 단계적인 작업 필요 → cross cutting concern 발생
1. SQLException을 잡긴 하고 던지긴 했는데 귀찮다..
2. 비즈니스 로직이 한줄 밖에 없고 다른 것들은 다 횡단관심사네
3. Connection, PreparedStatement 등 리소스 관리 너무 귀찮다..
@Transactional: DB 접근 기술과 무관한 선언적 Transaction 처리 (PSA)
➡️ 우리가 작성해야 하는 건 mapper.xml!
<mapper> : mapper 파일의 root element<insert> : 처리하려는 작업의 성격에 따라 insert, update, delete, select 태그@Configuration@MapperScan으로 @Mapper 검색 ⚠️ insert나 update Test 시에 조심!
@Transactional // test에서는 자동 rollback
#{parameterName} → 결과적으로 PreparedStatement의 ? 로 대체 association 활용!
<resultMap type="Address" id="addressMemberMap" extends="addressMap">
<association property="member" column="mno" resultMap="com.ssafy.live.model.dao.MemberDao.memberMap"></association>
</resultMap>
collection : resultMap의 하위 태그 property : 연동할 객체의 속성 명 column : join 관계에서 사용된 컬럼 명 ofType : List에 담길 N에 해당하는 객체의 타입 resultMap : 다른 resultMap을 재사용할 때 (다른 mapper를 사용할 경우 namespace 포함)columnPrefix : 두 테이블의 컬럼 이름이 동일해서 구별해야 할 경우 prefix 적용notNullColumn : 해당 값이 null일 경우 collection에 추가하지 않음 <resultMap type="Member" id="memberAddressMap" extends="memberMap">
<collection property="addresses" column="mno" ofType="Address" notNullColumn="ano"
resultMap="com.ssafy.live.model.dao.AddressDao.addressMap"></collection>
</resultMap>
⚠️ notNullColumn="ano"를 안해줄 경우 null 값으로 채워진 list가 한번은 도착해서 문제가 된다!