귀찮은 일
<insert id="insertDoctor"parameterType="domain.Doctor">
insert into Doctor (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateDoctor" parameterType="domain.Doctor">
update Doctor set
username = #{username}, password = #{password},
email = #{email}, bio = #{bio}
where id = #{id}
</update>
<delete id="deleteDoctor” parameterType="int">
delete from Doctor where id = #{id}
</delete>
<select id="selectDoctor" resultType="domain.Doctor">
select * from Doctor
</select>
3
4.
머리 아픈 일
<hibernate-mapping>
<classname="hello.Message“ table="MESSAGES">
<id name="id" column="MESSAGE_ID">
<generator class="increment"/>
</id>
<property name="text" column="MESSAGE_TEXT"/>
<many-to-one name="nextMessage" cascade="all"
column="NEXT_MESSAGE_ID"/>
</class>
</hibernate-mapping>
SELECT new list(mother, offspr, mate.name)
FROM DomesticCat AS mother
INNER JOIN mother.mate AS mate
LEFT OUTER JOIN mother.kittens AS offspr
4
5.
하고 싶은 일
•SQL 작성 최소화
• Object oriented programming
• 로직에 집중
• 단순한 설정 - 쉽고, 직관적
• 학습의 최소화
5
고려해야 할 점
•설정
– object, relation 매핑
• SQL 생성
– object 를 SQL 의 파라미터로 전달
– SQL 결과를 object 로 리턴
8
9.
구현 전략
• object와 relation 의 1:1 매핑 구현
– MyBatis 를 이용하여 기본적인 insert, update,
delete, select 문을 runtime 자동 생성
– 생성된 SQL문을 MyBatis SQL repository 에
저장
– Association 은 다루지 않음
– Join, subquery 구문은 MyBatis로 처리
• 설정은 Java Annotation 사용
• 일단 MySQL 먼저
9
10.
Java Annotation
• 자바5.0 에서 소개
• 자바 소스 코드에 추가되는 문법적인 메타데이터
• 클래스, 메소드, 변수, 파라미터, 패키지에 첨언하
여 컴파일러의 의해 .class 파일에 포함되어 컴파일
혹은 런타임 시 이용
• 번거로운 설정 작업들과 반복적인 코드를 줄여줌
• Built-in Annotations
– @Override, @Deprecated, @SupressWarnings
• Custom Annotations
– @Controller, @Service, @Entity, @Column
10
11.
Custom Annotation
• @interface선언
public @interface MyAnnotation {
String value();
}
• Annotation 추가
import MyAnnotation
@MyAnnotation(value=“my annotation”)
public void myMethod(int arg) {
// do something
}
11
12.
Annotation API
• Class와 Field
– getAnnotation(Class<A> annotationClass)
특정 타입에 대한 annotation 을 리턴
– getAnnotations()
모든 타입의 annotation 을 리턴
– isAnnotationPresent(Class annotationClass)
특정 타입에 대한 annotation 이 존재하면
true 리턴
12
13.
MyBatis
• 구) iBatis
•SQL문과 객체를 매핑
• SQL문을 XML 파일에 저장
• JDBC 코드 제거
13
출처) www.mybatis.org
14.
MyBatis 예제
• MappedStatement
<mapper namespace="org.mybatis.example.HospitalMapper">
<select id="selectHospital" parameterType="int"
resultType="Hospital">
select * from Hospital where id = #{id}
</select>
</mapper>
• Java DAO code
public interface HospitalMapper {
public Hospital selectHospital(int id);
}
HospitalMapper mapper = session.getMapper(HospitalMapper.class);
Hospital hospital = mapper.selectHospital(101);
14
15.
순서
1. Table 생성
2.Annotation 정의
3. Mapping class 생성
4. EntityManager 작성 – CRUD interface
5. SQL Generation 클래스 작성
– InsertSqlSource
– UpdateSqlSource
– DeleteSqlSource
– SelectOneSqlSource
– SelectListSqlSource
15
16.
1. Table 생성
Createtable hospital (
hospitalid INT NOT NULL
PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30),
regdttm DATETIME
)
16
5. SQL Generation
•INSERT
– 컬럼 중 auto_increment 로 선언된 컬럼은 insert 문
에서 제외
• UPDATE
– Primary Key 가 아닌 컬럼들만 update
– PK로 where 조건절 생성
• DELETE
– parameter 객체에서 null 값이 아닌 field 로 where 조
건절 생성
• SELECT
– parameter 객체에서 null 값이 아닌 field 로 where 조
건절 생성
21
22.
5-1. Insert문 생성
•컬럼 중 auto_increment 로 선언된 컬럼은
insert 문에서 제외
<생성되는 SQL>
INSERT INTO hospital (name, regdttm)
VALUES (#{name}, #{regdttm})
22
AnnotationUtil.getNonAutoIncrem
entColumnNames
1: List<String> names= new LinkedList<String>();
2: for (Field field : clazz.getDeclaredFields()) {
3: if (field.isAnnotationPresent(Column.class)) {
4: Column c = field.getAnnotation(Column.class);
5: if (!c.autoIncrement())
6: names.add("".equals(c.name()) ? field.getName():c.name());
7: }
8: }
9: return names;
26
27.
5-2. Update문 생성
•Primary Key 가 아닌 컬럼들만 update
• PK로 where 조건절 생성
<생성되는 SQL>
UPDATE hospital
SET name = #{name}, regdttm = #{regdttm}
WHERE hospitalid = #{hospitalid}
27
UpdateSqlSource
String sql =String.format(
"UPDATE %1$s SET %2$s WHERE %3$s",
AnnotationUtil.getTableName(clazz),
StringUtil.join(
AnnotationUtil.getNonPrimaryKeyColumnNames(clazz),
"%1$s = #{%1$s}", ", "),
StringUtil.join(
AnnotationUtil.getPrimaryKeyColumnNames(clazz),
"%1$s = #{%1$s}"," AND "));
parse(sqlSourceParser, sql, clazz);
29
30.
AnnotationUtil.getNonPrimaryKey
ColumnNames
1: List<String> names= new LinkedList<String>();
2: for (Field field : clazz.getDeclaredFields()) {
3: if (field.isAnnotationPresent(Column.class)) {
4: Column c = field.getAnnotation(Column.class);
5: if (!c.primaryKey())
6: names.add("".equals(c.name()) ? field.getName() :
7: c.name());
8: }
9: }
10: return names;
30
31.
AnnotationUtil.getPrimaryKeyColu
mnNames
List<String> names =new LinkedList<String>();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Column.class)) {
Column c = field.getAnnotation(Column.class);
if (c.primaryKey())
names.add("".equals(c.name()) ? field.getName() : c.name());
}
}
return names;
31
32.
5-3. Delete문 생성
•parameter 객체에서 null 값이 아닌 field 로
where 조건절 생성
예)
Hospital hospital = new Hospital();
hospital.setName(“JCO병원”);
entityManager.delete(hospital);
<생성되는 SQL>
DELETE FROM hospital
WHERE name = #{name}
32
5-4. Select문 생성
•parameter 객체에서 null 값이 아닌 field 로 where
조건절 생성
예)
Hospital hospital = new Hospital();
hospital.setName(“JCO병원”);
hospital = (Hospital)entityManager.load(hospital);
<생성되는 SQL>
SELECT hospitalid, name, regdttm
FROM hospital
WHERE name = #{name}
35