내부조인 : select * from dept left outer emp e join on d.deptno = e.deptno;
외부조인 : select * from dept d left outer join emp e on d.deptno = e.deptno;
와 같이 SQL쿼리를 사용하여 조인할 수 있다.
이렇게 값을 얻어서 VO에 넣어서 저장하기가 애매(?)할 수가 있다.
Mybatis를 이용하여 조인을 처리하여 VO의 저장할 수 있는 방법이 있다.
collection은 1:多관계에서 쓰이는 방법으로 부모의 레코드를 뽑아내면서 해당 레코드를 참조하는 자식의 레코드들을 뽑아낼 수 있다. -> 어떻게보면 이중포문과 비슷하다고 생각이 들 수 있다.
사용하게되는 태그 resultMap과 select면 된다.
resultMap은 select태그의 속성 중 resultMap이라는 속성이 존재한다.
resultMap을 먼저 선언한 뒤, select에서 참조하는 방법이다.
<!-- 조인 시 VO가 두개의 컬럼을 감당할 수 있어야함... -->
<!-- 쿼리결과와 객체간 매핑을 자동으로 하는 것이 아니라,
개발자가 주도하여 처리를 하고 싶을때는 별도의 매핑을 선언.. -->
<!-- 매핑의 커스터마이징 -->
<resultMap type="Dept" id="deptJoinEmp">
<!-- column=query에서 뽑아진 컬럼명 -->
<id column="deptno" property="deptno"/><!-- primary key -->
<result column="dname" property="dname"/><!-- 일반컬럼 -->
<result column="loc" property="loc"/>
<!-- 부서정보가져오고 부서정보에 포함되는 외부에 있는 부서원정보가져오기-->
<!-- Emp(ofType)로 구성된 List(javaType)-->
<!-- deptno컬럼을 가져오겠다. -->
<!-- propery는 set메서드를 생각 -->
<collection column="deptno" javaType="java.util.List" ofType="Emp" select="Emp.select" property="empList"/>
</resultMap>
<!-- 이중포문과 비슷 dept정보를 가져올 때 그 정보를 가지고 emp정보를 가져오고 다음 dept가져오면 그 dept에 대한 emp를 뽑아온다. -->
<select id="selectAll" resultMap="deptJoinEmp">
select deptno, dname, loc from dept
</select>
resultMap은 매핑을 개발자가 커스터마이징하여 내가 만든 VO에 맞게 조인할 수 있다.
resultMap태그의 속성 중 type은 만들 VO객체를 말하고 id는 select에서 참조할 수 있게 이름을 지어주는 것이다.
id는 테이블의 primary key를 매핑하는 것이고, result는 일반 컬럼들을 매핑하는 것이다.
위 태그의 속성 중 column은 쿼리로 뽑아배는 레코드의 컬럼을 말하고, property는 VO객체의 set메서드를 말한다.
collection의 속성 중 javaType은 만들 자료형을 말하고 ofType은 javaType이 List와 같은 제네릭형일 때 자료형을 정해준다. select는 자식의 Mapper에서의 사용할 쿼리id를 말한다.
아래의 코드로 예를 들어본다면, Student클래스내에 각 메서드들의 실행 시작과 실행 후에 Bell클래스의 메서드인 startBell(), endBell()실행하도록 만들어봄으로써 AOP를 이해할 수 있다.
package test;
public class Student {
public void study1() { //영어시간
// System.out.println("♬ 시작 종"); //종이 울리는 것은 학생과 관련된 기능이 아님!!! 그리고 중복된다.
System.out.println("1교시는 영어시간이에요");
}
public void study2() {//국어시간
System.out.println("2교시는 영어시간이에요");
}
public void study3() {//물리시간
System.out.println("3교시는 물리시간이에요");
}
public void study4() {//수학시간
System.out.println("4교시는 수학시간이에요");
}
}
package test;
public class Bell {
public void startBell() {
System.out.println("♬ 시작 종");
}
public void endBell() {
System.out.println("♬ 종료 종");
}
}
<!-- 학생과 벨을 엮어보자(weaving) -->
<!-- AOP를 이용하기 위해서는, 공통로직 즉 횡단적 관심사항을 등록한다!! -->
<bean id="bell" class="test.Bell"/>
<!-- 어떤 시점에, 어떤 객체에게 횡단점 관심사항을 적용할지 xml태그로 서술한다..
즉 프로그램 코드가 아닌 xml과 같은 설정파일에서 구현하는 방법을 선언적이라한다..
-->
<aop:config>
<aop:aspect id="bellAspect" ref="bell">
<!-- 어떤 시점에 벨이 관여할지를 결정 -->
<!-- test..*(..) 테스트 패키지 아래의 모든 클래스의 모든 메서드 -->
<aop:pointcut expression="execution(public * test.Student.*(..))" id="bellpointcut"/>
<aop:pointcut expression="execution(public * test.Dog.*(..))" id="pointcutToDog"/>
<!-- 공통기능 동작을 언제 할지, 즉 학생의 동작 이전에 적용, 이후에 동작시킬지.. -->
<aop:before method="startBell" pointcut-ref="bellpointcut"/>
<aop:after method="endBell" pointcut-ref="bellpointcut"/>
<aop:before method="startBell" pointcut-ref="pointcutToDog"/>
<aop:after method="endBell" pointcut-ref="pointcutToDog"/>
</aop:aspect>
</aop:config>
<bean id="student" class="test.Student"/>
<bean id="dog" class="test.Dog"/>
Bell클래스의 인스턴스가 Student의 메서드들의 실행을 관찰하고 있다고 생각하면 쉬운 것 같다.