Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads.
Java Annotation과 MyBatis로
나만의 ORM Framework을 만들어보자
2011 JCO 11th Conference | Session ${track_#}-${session_#} | Javacommun...
하기 싫은 일
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager.getConnection();
PreparedStatement stmt = c.p...
귀찮은 일
<insert id="insertDoctor" parameterType="domain.Doctor">
insert into Doctor (id,username,password,email,bio)
values ...
머리 아픈 일
<hibernate-mapping>
<class name="hello.Message“ table="MESSAGES">
<id name="id" column="MESSAGE_ID">
<generator cl...
하고 싶은 일
• SQL 작성 최소화
• Object oriented programming
• 로직에 집중
• 단순한 설정 - 쉽고, 직관적
• 학습의 최소화
5
ORM? Hibernate?
6
Hibernate + MyBatis?
7
고려해야 할 점
• 설정
– object, relation 매핑
• SQL 생성
– object 를 SQL 의 파라미터로 전달
– SQL 결과를 object 로 리턴
8
구현 전략
• object 와 relation 의 1:1 매핑 구현
– MyBatis 를 이용하여 기본적인 insert, update,
delete, select 문을 runtime 자동 생성
– 생성된 SQL문을 My...
Java Annotation
• 자바 5.0 에서 소개
• 자바 소스 코드에 추가되는 문법적인 메타데이터
• 클래스, 메소드, 변수, 파라미터, 패키지에 첨언하
여 컴파일러의 의해 .class 파일에 포함되어 컴파일
혹...
Custom Annotation
• @interface 선언
public @interface MyAnnotation {
String value();
}
• Annotation 추가
import MyAnnotation
@...
Annotation API
• Class 와 Field
– getAnnotation(Class<A> annotationClass)
특정 타입에 대한 annotation 을 리턴
– getAnnotations()
모든 타...
MyBatis
• 구) iBatis
• SQL문과 객체를 매핑
• SQL문을 XML 파일에 저장
• JDBC 코드 제거
13
출처) www.mybatis.org
MyBatis 예제
• Mapped Statement
<mapper namespace="org.mybatis.example.HospitalMapper">
<select id="selectHospital" paramete...
순서
1. Table 생성
2. Annotation 정의
3. Mapping class 생성
4. EntityManager 작성 – CRUD interface
5. SQL Generation 클래스 작성
– Insert...
1. Table 생성
Create table hospital (
hospitalid INT NOT NULL
PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30),
regdttm DATETIME...
2. Annotation 정의
public @interface Table {
String value() default "";
}
public @interface Column {
String name() default "...
3. Mapping Class
@Table(“hospital”)
Public class Hospital {
@Column(primaryKey=true,
autoIncrement=true)
private Integer h...
4. EntityManager
void insert(Object parameter)
void update(Object parameter)
void delete(Object parameter)
Object load(Obj...
EntityManager 사용예
EntityManager entityManager = new EntityManager();
Hospital hospital = new Hospital();
hospital.setHospi...
5. SQL Generation
• INSERT
– 컬럼 중 auto_increment 로 선언된 컬럼은 insert 문
에서 제외
• UPDATE
– Primary Key 가 아닌 컬럼들만 update
– PK로 wh...
5-1. Insert문 생성
• 컬럼 중 auto_increment 로 선언된 컬럼은
insert 문에서 제외
<생성되는 SQL>
INSERT INTO hospital (name, regdttm)
VALUES (#{na...
EntityManager.insert()
1: Class<?> clazz = object.getClass();
2: String statementName = PREFIX_INSERT +
3: clazz.getSimple...
InsertSqlSource
1: List<String> columnNames =
2: AnnotationUtil.getNonAutoIncrementColumnNames(clazz);
3: String sql = Str...
AnnotationUtil.getTableName
Table t = clazz.getAnnotation(Table.class);
return t.value();
25
AnnotationUtil.getNonAutoIncrem
entColumnNames
1: List<String> names = new LinkedList<String>();
2: for (Field field : cla...
5-2. Update문 생성
• Primary Key 가 아닌 컬럼들만 update
• PK로 where 조건절 생성
<생성되는 SQL>
UPDATE hospital
SET name = #{name}, regdttm =...
EntityManager.update()
1: Class<?> clazz = object.getClass();
2: String statementName = PREFIX_UPDATE +
3: clazz.getSimple...
UpdateSqlSource
String sql = String.format(
"UPDATE %1$s SET %2$s WHERE %3$s",
AnnotationUtil.getTableName(clazz),
StringU...
AnnotationUtil.getNonPrimaryKey
ColumnNames
1: List<String> names = new LinkedList<String>();
2: for (Field field : clazz....
AnnotationUtil.getPrimaryKeyColu
mnNames
List<String> names = new LinkedList<String>();
for (Field field : clazz.getDeclar...
5-3. Delete문 생성
• parameter 객체에서 null 값이 아닌 field 로
where 조건절 생성
예)
Hospital hospital = new Hospital();
hospital.setName(“...
EntityManager.delete()
1: Class<?> clazz = object.getClass();
2: String statementName = PREFIX_DELETE + clazz.getSimpleNam...
DeleteSqlSource
1: public DeleteSqlSource(SqlSourceBuilder sqlSourceParser,
2: Class<?> clazz) {
3: super(sqlSourceParser)...
5-4. Select문 생성
• parameter 객체에서 null 값이 아닌 field 로 where
조건절 생성
예)
Hospital hospital = new Hospital();
hospital.setName(“...
EntityManager.load()
1: Class<?> clazz = object.getClass();
2: String statementName = PREFIX_LOAD + clazz.getSimpleName();...
SelectOneSqlSource
1: public SelectOneSqlSource(SqlSourceBuilder sqlSourceParser, Class<?> clazz) {
2: super(sqlSourcePars...
복습
1. Table 생성
2. Annotation 정의
3. Mapping class 생성
4. EntityManager 작성 – CRUD interface
5. SQL Generation 클래스 작성
– Insert...
Effect
• 비타민MD 사이트에 일부 적용
• 만약 전체 적용한다면
69% SQL문 제거 가능
39
SQL 적용 전 적용 후
insert 112 7
update 80 2
delete 79 0
select 327 17...
Future Work
• Annotation 추가
– Like 구문 지원
– DDL 상의 default 값, not null 등의 constraint
지원
• Transaction
• Caching
• Oracle, M...
Contact
http://code.google.com/p/mybatis-orm
wolfkang@gmail.com
41
Do It Yourself and Have Fun.
42
이 저작물은 크리에이티브 커먼스 코리아 저작자표시-비영리-
동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
This work is Licensed under Creative Commons Kore...
Upcoming SlideShare
Loading in …5
×

Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자

1,159 views

Published on

Java Annotation 과 MyBatis를 활용하여 ORM 프레임웍을 직접 만들 수 있는 기법에 대해 소개합니다.

Published in: Software
  • Be the first to comment

Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자

  1. 1. Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자 2011 JCO 11th Conference | Session ${track_#}-${session_#} | Javacommunity.Org 강동혁 (한솔헬스케어) [email protected] Revision: 20110612
  2. 하기 싫은 일 Class.forName("com.mysql.jdbc.Driver"); Connection c = DriverManager.getConnection(); PreparedStatement stmt = c.prepareStatement ("select title, year_made from movies " + "where year_made >= ?" + " and year_made < ?"); for(int decadeStart = 1920; decadeStart < 2000; decadeStart += 10){ stmt.setInt(1, decadeStart); stmt.setInt(2, decadeStart + 10); ResultSet rs = stmt.executeQuery(); while(rs.next()){ System.out.println(rs.getString(1) + " (" + rs.getInt(2) + ")"); } } 2
  3. 귀찮은 일 <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> <class name="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
  6. ORM? Hibernate? 6
  7. Hibernate + MyBatis? 7
  8. 고려해야 할 점 • 설정 – 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 예제 • Mapped Statement <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 생성 Create table hospital ( hospitalid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(30), regdttm DATETIME ) 16
  17. 2. Annotation 정의 public @interface Table { String value() default ""; } public @interface Column { String name() default ""; boolean primaryKey() default false; boolean autoIncrement() default false; } 17
  18. 3. Mapping Class @Table(“hospital”) Public class Hospital { @Column(primaryKey=true, autoIncrement=true) private Integer hospitalid; @Column private String name; @Column(name=“regdttm”) private Date regdttm; } 18
  19. 4. EntityManager void insert(Object parameter) void update(Object parameter) void delete(Object parameter) Object load(Object parameter) List list(Object parameter) List list(Object parameter, String orderby) List list(Object parameter, String orderby, int rows) 19
  20. EntityManager 사용예 EntityManager entityManager = new EntityManager(); Hospital hospital = new Hospital(); hospital.setHospitalid(12345); hospital.setName(“JCO병원”); hospital.setRegdttm(new Date()); entityManager.insert(hospital); hospital = entityManager.load(hospital); hospital.setName(“JCO병원”); entityManager.update(hospital); entityManager.delete(hospital); 20
  21. 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
  23. EntityManager.insert() 1: Class<?> clazz = object.getClass(); 2: String statementName = PREFIX_INSERT + 3: clazz.getSimpleName(); 4: if (!configuration.hasStatement(statementName)) { 5: addMappedStatement( 6: statementName, 7: new InsertSqlSource(sqlSourceParser,clazz), 8: SqlCommandType.INSERT,null); 9: } 10: getSqlSession().insert(statementName, object); 23
  24. InsertSqlSource 1: List<String> columnNames = 2: AnnotationUtil.getNonAutoIncrementColumnNames(clazz); 3: String sql = String.format( 4: “INSERT INTO %1$s ( %2$s ) VALUES ( %3$s ) ", 5: AnnotationUtil.getTableName(clazz), 6: StringUtil.join(columnNames, ","), 7: StringUtil.join(columnNames, "#{%1$s}",",")); 8: parse(sqlSourceParser, sql, clazz); 24
  25. AnnotationUtil.getTableName Table t = clazz.getAnnotation(Table.class); return t.value(); 25
  26. 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
  28. EntityManager.update() 1: Class<?> clazz = object.getClass(); 2: String statementName = PREFIX_UPDATE + 3: clazz.getSimpleName(); 4: if (!configuration.hasStatement(statementName)) { 5: addMappedStatement( 6: statementName, 7: new UpdateSqlSource(sqlSourceParser,clazz), 8: SqlCommandType.UPDATE,null); 9: } 10: getSqlSession().update(statementName, object); 28
  29. 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
  33. EntityManager.delete() 1: Class<?> clazz = object.getClass(); 2: String statementName = PREFIX_DELETE + clazz.getSimpleName(); 3: if (!configuration.hasStatement(statementName)) { 4: addMappedStatement( 5: statementName, 6: new DeleteSqlSource(sqlSourceParser,clazz), 7: SqlCommandType.DELETE,null); 8: } 9: getSqlSession().delete(statementName, object); 33
  34. DeleteSqlSource 1: public DeleteSqlSource(SqlSourceBuilder sqlSourceParser, 2: Class<?> clazz) { 3: super(sqlSourceParser); 4: staticSql = "DELETE FROM” 5: +AnnotationUtil.getTableName(clazz); 6: } 7: public BoundSql getBoundSql(Object parameterObject) { 8: String sql = staticSql + " WHERE " + 9: StringUtil.join( 10: AnnotationUtil.getNotNullColumnNames(parameterObject), 11: "%1$s = #{%1$s}"," AND "); 12: return getBoundSql(sql,parameterObject); 13: } 34
  35. 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
  36. EntityManager.load() 1: Class<?> clazz = object.getClass(); 2: String statementName = PREFIX_LOAD + clazz.getSimpleName(); 3: if (!configuration.hasStatement(statementName)) { 4: addMappedStatement(statementName, 5: new SelectOneSqlSource(sqlSourceParser,clazz), 6: SqlCommandType.SELECT,clazz); 7: } 8: Object result = getSqlSession().selectOne(statementName, object); 9: if (result != null) 10: BeanUtils.copyProperties(result, object); 11: return result; 36
  37. SelectOneSqlSource 1: public SelectOneSqlSource(SqlSourceBuilder sqlSourceParser, Class<?> clazz) { 2: super(sqlSourceParser); 3: staticSql = String.format("SELECT %1$s FROM %2$s ", 4: StringUtil.join(AnnotationUtil.getColumnNames(clazz),", "), 5: AnnotationUtil.getTableName(clazz)); 6: } 7: 8: public BoundSql getBoundSql(Object parameterObject) { 9: String sql = staticSql + " WHERE " + 10: StringUtil.join( 11: AnnotationUtil.getNotNullColumnNames(parameterObject), 12: "%1$s = #{%1$s}"," AND ") + 13: " LIMIT 1"; 14: return getBoundSql(sql,parameterObject); 15: } 37
  38. 복습 1. Table 생성 2. Annotation 정의 3. Mapping class 생성 4. EntityManager 작성 – CRUD interface 5. SQL Generation 클래스 작성 – InsertSqlSource – UpdateSqlSource – DeleteSqlSource – SelectOneSqlSource – SelectListSqlSource 38
  39. Effect • 비타민MD 사이트에 일부 적용 • 만약 전체 적용한다면 69% SQL문 제거 가능 39 SQL 적용 전 적용 후 insert 112 7 update 80 2 delete 79 0 select 327 176 총 598 185
  40. Future Work • Annotation 추가 – Like 구문 지원 – DDL 상의 default 값, not null 등의 constraint 지원 • Transaction • Caching • Oracle, MSSQL, DB2 등 다른 DBMS 지원 40
  41. Contact http://code.google.com/p/mybatis-orm [email protected] 41
  42. Do It Yourself and Have Fun. 42
  43. 이 저작물은 크리에이티브 커먼스 코리아 저작자표시-비영리- 동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다. This work is Licensed under Creative Commons Korea Attribution 2.0 License.
http://best-cooler.reviews

bestseller.reviews/the-top-5-best-sites-to-buy-stock-photos-online-and-save-2/

karter-kiev.net

×