orm을 맞이하는 우리의 자세
TRANSCRIPT
![Page 1: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/1.jpg)
ORM 을 맞이하는 우리의 자세
정병태
![Page 2: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/2.jpg)
랑겔한스 : 정병태
- Web Developer
- OKKY.KR Contributor
- https://github.com/1angerhans - http://okky.kr/user/info/26138 - [email protected]
![Page 3: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/3.jpg)
‘나는 SQL 이 싫어요.’
![Page 4: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/4.jpg)
ORMObject Relational Mapping
![Page 5: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/5.jpg)
– Wikipedia 인용
“Object-relational mapping (ORM, O/RM, and O/R mapping) in computer science is a programming technique for converting data between
incompatible type systems in object-oriented programming languages.”
![Page 6: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/6.jpg)
– Wikipedia 인용
“객체 관계 매핑(Object-relational mapping; ORM)은 데이터베이스와 객체 지향 프로그래밍 언어 간의 호환되지 않는 데이터를 변환하는 프로그래밍 기법이다.”
![Page 7: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/7.jpg)
Object-relational impedance mismatch
- Data type differences - Structural and integrity differences - Manipulative difference - Transactional differences
https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch
![Page 8: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/8.jpg)
문제의 해결 Without ORM
![Page 9: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/9.jpg)
현실의 문제 #1
![Page 10: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/10.jpg)
Vo, DTO 그리고 Table들
![Page 11: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/11.jpg)
D.D.DDomain Driven Design
![Page 12: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/12.jpg)
Domain Entity 설계
![Page 13: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/13.jpg)
CREATE TABLE TBL_MSG ( F_GRP_ID INT(6) NOT NULL PRIMARY KEY , PTN_ID INT(6) , PRIORITY INT(6) , JOB_CODE INT(6) , FLAG_PRO INT(6) , CHAINNUM INT(6) , MASSNUM INT(6) , USERID VARCHAR(20) , CPCODE VARCHAR(20) , QTCODE VARCHAR(20) , MSGSEPER CHAR(1) , MSG_CNT INT(6) , CNTPSEC INT(6) ,
흔한 Legacy Table
![Page 14: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/14.jpg)
Minimization
![Page 15: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/15.jpg)
CREATE TABLE TBL_USER (
SEQ INT(6) NOT NULL PRIMARY KEY ,
USER_TYPE VARCHAR(20) ,
AUTH_TYPE VARCHAR(20) ,
USERID VARCHAR(20) ,
NAME VARCHAR(20) ,
PASS VARCHAR(20) ,
TEL VARCHAR(12) ,
CELL VARCHAR(12) ,
OFFICE_TEL VARCHAR(12) ,
EMAIL VARCHAR(200) ,
ZIPCODE VARCHAR(7) ,
ADDRESS_01 VARCHAR(200) ,
ADDRESS_02 VARCHAR(200) ,
COMPANY_NAME VARCHAR(20) ,
QUARTER_NAME VARCHAR(20) ,
STATUS VARCHAR(20) ,
MILEAGE INT(12) ,
REG_DATE DATE ,
PASS_CHG_DATE DATE ,
PASS_FAIL_CNT INT(6)
);
User
Contact
Company
Domains
Auth
Mileage
![Page 16: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/16.jpg)
CREATE TABLE TBL_USER (
SEQ INT(6) NOT NULL PRIMARY KEY ,
USER_TYPE VARCHAR(20) ,
USERID VARCHAR(20) ,
NAME VARCHAR(20) ,
PASS VARCHAR(20) ,
STATUS VARCHAR(20) ,
REG_DATE DATE ,
PASS_CHG_DATE DATE ,
PASS_FAIL_CNT INT(6)
);
CREATE TABLE TBL_COMPANY (
SEQ INT(6) NOT NULL PRIMARY KEY ,
COMPANY_NAME VARCHAR(20) ,
STATUS VARCHAR(20) ,
REG_DATE DATE
);
CREATE TABLE TBL_AUTH (
SEQ INT(6) NOT NULL PRIMARY KEY ,
ROLE VARCHAR(20)
);
CREATE TABLE TBL_ADDRESS (
ZIPCODE VARCHAR(7) ,
ADDRESS_01 VARCHAR(200) ,
ADDRESS_02 VARCHAR(200)
);
CREATE TABLE TBL_CONTACT (
SEQ INT(6) NOT NULL PRIMARY KEY ,
TEL VARCHAR(12) ,
CELL VARCHAR(12)
);
CREATE TABLE TBL_MILEAGE (
SEQ INT(6) NOT NULL PRIMARY KEY ,
POINT INT(12)
);
![Page 17: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/17.jpg)
public class User { Long seq; String userid; String userpass; String username; Date regDate;
Company company; Address address; Contact contact; Mileage mileage;
List<Auth> authorities;
// Getter & Setter }
public class Company { … }
public class Address { … }
public class Contact { … }
public class Mileage { … }
public class Auth { … }
![Page 18: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/18.jpg)
현실의 문제 #2
![Page 19: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/19.jpg)
DBA
![Page 20: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/20.jpg)
CREATE TABLE TBL_USER (
SEQ INT(6) NOT NULL PRIMARY KEY ,
USER_TYPE VARCHAR(20) ,
USERID VARCHAR(20) ,
NAME VARCHAR(20) ,
PASS VARCHAR(20) ,
STATUS VARCHAR(20) ,
REG_DATE DATE ,
PASS_CHG_DATE DATE ,
PASS_FAIL_CNT INT(6)
);
CREATE TABLE TBL_COMPANY (
SEQ INT(6) NOT NULL PRIMARY KEY ,
COMPANY_NAME VARCHAR(20) ,
STATUS VARCHAR(20) ,
REG_DATE DATE
);
CREATE TABLE TBL_AUTH (
SEQ INT(6) NOT NULL PRIMARY KEY ,
ROLE VARCHAR(20)
);
CREATE TABLE TBL_ADDRESS (
ZIPCODE VARCHAR(7) ,
ADDRESS_01 VARCHAR(200) ,
ADDRESS_02 VARCHAR(200)
);
CREATE TABLE TBL_CONTACT (
SEQ INT(6) NOT NULL PRIMARY KEY ,
TEL VARCHAR(12) ,
CELL VARCHAR(12)
);
CREATE TABLE TBL_MILEAGE (
SEQ INT(6) NOT NULL PRIMARY KEY ,
POINT INT(12)
);
![Page 21: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/21.jpg)
DBA 들이 나를 향해 이렇게 외친다.
![Page 22: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/22.jpg)
public class MSG {
int grpnum; int chainnum; String userid; String usernm; String cpcode; String qtcode; String title; String sndTitle; String cComment; String dstaddr; String callback; String msgTemplet; String reservData;
흔한 Legacy Model
![Page 23: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/23.jpg)
Mybatis Association
![Page 24: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/24.jpg)
<select id="selectOne" resultMap=“userMap">
select u.seq, u.userid, u.pass, u.name, u.tel, u.cel, u.email, u.company_name, u.zipcode, u.address_01, u.address_02 …. from tbl_user u where u.seq = #{seq}
</select>
Mybatis
![Page 25: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/25.jpg)
Mybatis Association<resultMap id="userMap" type=“User">
<id jdbcType="INTEGER" property="seq" column="seq"/> <result jdbcType="VARCHAR" property="userid" column="userid"/> <result jdbcType="VARCHAR" property="pass" column="pass"/>
<association property="company" javaType="Company" > <result jdbcType="VARCHAR" property=“company_name" column="cpname"/> </association>
<association property="contact" javaType="Contact" > <result jdbcType="VARCHAR" property=“company_name" column="cpname"/> </association>
<association property="address" javaType="Address" > <result jdbcType="VARCHAR" property=“zopcode" column=“zopcode"/> <result jdbcType="VARCHAR" property=“address_01” column=“address_01"/> <result jdbcType="VARCHAR" property=“address_01” column="address_01"/> </association>
<collection property="authorities" select="selectUserAuthList" fetchType="lazy" column="{seq=seq}" />
</resultMap>
![Page 26: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/26.jpg)
– 미상
“인간의 욕심은 끝이 없고, 같은 실수를 반복한다.”
![Page 27: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/27.jpg)
With ORM
![Page 28: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/28.jpg)
Hibernate
![Page 29: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/29.jpg)
@Entity@Table( name = “TBL_USER" )public class User { Integer seq; String userid; String userpass; String username; Date regDate;
Company company; Address address; Contact contact; Mileage mileage;
List<Auth> authorities;
// Getter & Setter
@Id@GeneratedValue(generator="increment")@GenericGenerator(name="increment", strategy = “increment”)@Column(name = “SEQ”)
Long getSeq() { return seq;
}
}
@Entity@Table( name = “TBL_COMPANY" )public class Company { … }
@Entity@Table( name = “TBL_ADDRESS" )public class Address { … }
@Entity@Table( name = “TBL_CONTACT" )public class Contact { … }
@Entity@Table( name = “TBL_MILEAGE" )public class Mileage { … }
@Entity@Table( name = “TBL_AUTH" )public class Auth { … }
![Page 30: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/30.jpg)
CREATE TABLE TBL_USER (
SEQ INT(6) NOT NULL PRIMARY KEY ,
USER_TYPE VARCHAR(20) ,
USERID VARCHAR(20) ,
NAME VARCHAR(20) ,
PASS VARCHAR(20) ,
STATUS VARCHAR(20) ,
REG_DATE DATE ,
PASS_CHG_DATE DATE ,
PASS_FAIL_CNT INT(6)
);
CREATE TABLE TBL_COMPANY (
SEQ INT(6) NOT NULL PRIMARY KEY ,
COMPANY_NAME VARCHAR(20) ,
STATUS VARCHAR(20) ,
REG_DATE DATE
);
CREATE TABLE TBL_AUTH (
SEQ INT(6) NOT NULL PRIMARY KEY ,
ROLE VARCHAR(20)
);
CREATE TABLE TBL_ADDRESS (
ZIPCODE VARCHAR(7) ,
ADDRESS_01 VARCHAR(200) ,
ADDRESS_02 VARCHAR(200)
);
CREATE TABLE TBL_CONTACT (
SEQ INT(6) NOT NULL PRIMARY KEY ,
TEL VARCHAR(12) ,
CELL VARCHAR(12)
);
CREATE TABLE TBL_MILEAGE (
SEQ INT(6) NOT NULL PRIMARY KEY ,
POINT INT(12)
);
![Page 31: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/31.jpg)
DBA 들이 나를 향해 이렇게 외친다.
![Page 32: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/32.jpg)
CREATE TABLE TBL_USER (
SEQ INT(6) NOT NULL PRIMARY KEY ,
USER_TYPE VARCHAR(20) ,
AUTH_TYPE VARCHAR(20) ,
USERID VARCHAR(20) ,
NAME VARCHAR(20) ,
PASS VARCHAR(20) ,
TEL VARCHAR(12) ,
CELL VARCHAR(12) ,
OFFICE_TEL VARCHAR(12) ,
EMAIL VARCHAR(200) ,
ZIPCODE VARCHAR(7) ,
ADDRESS_01 VARCHAR(200) ,
ADDRESS_02 VARCHAR(200) ,
COMPANY_NAME VARCHAR(20) ,
QUARTER_NAME VARCHAR(20) ,
STATUS VARCHAR(20) ,
MILEAGE INT(12) ,
REG_DATE DATE ,
PASS_CHG_DATE DATE ,
PASS_FAIL_CNT INT(6)
);
User
Contact
Company
Domains
Auth
Mileage
![Page 33: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/33.jpg)
@Entity@Table( name = “TBL_USER" )public class User {
@Id@GeneratedValue(generator="increment")@GenericGenerator(name="increment", strategy = “increment”)@Column(name = “SEQ”)
Integer seq;
@Column(name = “USERID”) String userid;
@Embedded
Company company;
@Embedded
Address address;
@Embedded
Contact contact;
@OneToOne( cascade = CascadeType.ALL, fetch = FetchType.LAZY) Mileage mileage;
@OneToMany( cascade = CascadeType.ALL, fetch = FetchType.LAZY) List<Auth> authorities;
}
@Embeddable
public class Company { … }
@Embeddable
public class Address { … }
@Embeddable
public class Contact { … }
@Embeddable
public class Mileage { … }
@Embeddable
public class Auth { … }
![Page 34: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/34.jpg)
Criteria
![Page 35: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/35.jpg)
Criteria
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("seq", seq))
.setProjection(
Projections.projectionList()
.add(Projections.property(“zipcode"))
.add(Projections.property(“address_01"))
.add(Projections.property(“address_02")))
.setResultTransformer(
Transformers.aliasToBean(Address.class));
Address address = criteria.uniqueResult();
![Page 36: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/36.jpg)
HQL
![Page 37: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/37.jpg)
HQL
Address address = session.createQuery(“select u.zipcode,
u.address_01, u.address_02 from User u where seq = :seq”, )
.setParameter("seq", seq)
.setResultTransformer(
Transformers.aliasToBean(Address.class))
.uniqueResult();
![Page 38: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/38.jpg)
ORM 에 대한 단상
• Legacy DB 도 충분히 도입 가능하다.
• ORM을 염두한 디자인을 적용할 경우 생산성이 급격히 좋아진다.
• Criteria는 학습이 쉽지 않다.
• HQL을 쓸 때면 뭔가 손해보는 기분.. (방언 처리 라고는 하지만..)
• 퍼포먼스는 사실상 문제 없다.
• SQL Layer가 빠져야돼.
![Page 39: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/39.jpg)
ORM 은 우리가 가지고 있는 문제를 해결한
‘결과’가 아닌
더욱 나은 방향으로 가기 위한 ‘과정’ 입니다.
– 저
![Page 40: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/40.jpg)
No SQL
![Page 41: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/41.jpg)
SQL이 필요 없다고 RDBMS가 필요 없는건 아닐껍니다.
![Page 42: ORM을 맞이하는 우리의 자세](https://reader031.vdocuments.site/reader031/viewer/2022022411/58edfec91a28ab26688b45e3/html5/thumbnails/42.jpg)
공유의 시간