SlideShare a Scribd company logo
1 of 75
Download to read offline
© 2018 NHN FORWARD. All rights reserved.
MyBatis에서 JPA로
신동민
Dooray개발실
CONTENTS
1. Why MyBatis?
2. Why JPA?
3. What is JPA?
4. MyBatis to JPA
최근 5년간 구글 트렌드
MyBatis vs JPA(전 세계)
최근 5년간 구글 트렌드
MyBatis vs JPA(전 세계)
MyBatis < JPA
최근 5년간 구글 트렌드
MyBatis vs JPA – 지역별(전 세계)
최근 5년간 구글 트렌드
MyBatis vs JPA(한국)
최근 5년간 구글 트렌드
MyBatis vs JPA(한국)
MyBatis ≥ JPA
그 동안 MyBatis로 마이 버팃으면
이제는 JPA를 한 번 써 봐야 할 때
MyBatis에서 JPA로!
Why MyBatis?
JDBC를 좀더 편하게 사용할 수 있도록
객체를 SQL이나 저장 프로시저와 매핑해주는
퍼시스턴스 프레임워크 (persistence framework)
한 마디로, SQL Mapper
MyBatis
 다른 프레임워크들에 비해 간단하다 (Simple)
 소스 코드와 SQL의 분리(생산성, 작업 분배)
 SQL을 직접 다룰 수 있다(복잡한 쿼리, 함수, 저장 프로시저 등)
MyBatis의 장점
MyBatis in 2010
NEW HOME OF THE WORLD’S MOST POPULAR SQL MAPPING FRAMEWORK
도메인
MyBatis 예제 프로그램
REST API
MyBatis 예제 프로그램
MyBatis 예제 프로그램
 반복적인 코드와 CRUD SQL 작업
 SQL과 데이터베이스 벤더에 대한 종속성
MyBatis의 단점
Why JPA?
생산성
 JPA를 사용하면 지루하고 반복적인 CRUD용 SQL을 개발자가 직접 작성하지 않아도 된다
 Spring Data JPA를 사용하면 interface 선언만으로도 쿼리 구현이 가능하기 때문에
관리 도구 등에서 가볍게 사용할 수 있는 CRUD 쿼리를 손쉽게 대처할 수 있다
JPA를 사용해야 하는 이유
구분 Order Item OrderItem
insert insert into Orders ( … ) insert into Items ( … ) insert into OrderItems ( …)
update update Orders set … update Items set … update OrderItems set …
delete delete from Orders … delete from Items … delete from OrderItems …
… … … …
JPA를 사용해야 하는 이유
public class Item {
private Long itemId;
private String itemName;
private Long price;
private String category;
}
유지보수
 칼럼 추가/삭제 시 직접 관련된 CRUD 쿼리를 모두 수정하는 대신 JPA가 관리하는 모델(Entity)을 수정하면 된다
구분 Item
insert insert into Items ( item_id, item_name, price, category )
update update Items set item_name = ‘’, price = 0, category = ‘’
select select item_id, item_name, price, category from Items …
… …
데이터 접근 추상화와 벤더 독립성
 데이터베이스 벤더마다 미묘하게 다른 데이터 타입이나 SQL을 JPA를 이용하면 손쉽게 해결할 수 있다
JPA를 사용해야 하는 이유
Oracle MySql
SQL 중심적인 개발에서 객체 중심으로 개발
패러다임 불일치 해결
 JPA는 객체와 관계형 데이터베이스 사이의 패러다임의 불일치로 발생하는 문제를 해결
 (상속, 연관 관계, 객체 그래프 탐색 등)
JPA를 사용해야 하는 이유
What is JPA?
JPA
Java Persistence API
 자바 진영의 ORM 기술 표준
ORM(Object-Relational Mapping)
 데이터베이스 객체를 자바 객체로 매핑하여 객체 간의 관계를 바탕으로 SQL을 자동으로 생성
JPA
 표준 명세
 JSR 338 – Java Persistence 2.2
Hibernate
 JPA 실제 구현체 : Hibernate, EclipseLink, DataNuclues
 Hibernate가 사실상 표준(de facto)
JPA, Hibernate
Spring Data
 다양한 데이터 저장소에 대한 접근을 추상화하기 위한 Spring 프로젝트
 JPA, JDBC, Redis, MongoDB, Elasticsearch 등
Spring Data JPA
 Repository 추상화를 통해 interface 선언만으로도 구현 가능
 메서드 이름으로 쿼리 생성
 Web Support(페이징, 정렬, 도메인 클래스 컨버터 등)
Spring Data JPA
MyBatis to JPA
MyBatis to JPA
JPA 설정
org.springframework.data:spring-data-jpa
org.hibernate:hibernate-entitymanager
의존성 라이브러리 추가
 Spring Data JPA, Hibernate 사용
JPA 설정
빈 설정 – EntityManagerFactory
 LocalContainerEntityManagerFactoryBean 빈 등록
 SqlSessionFactoryBean vs EntityManagerFactoryBean
JPA 설정
@Bean LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf
= new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource);
emf.setPackagesToScan("com.nhnent.forward.mybatistojpa.entity");
emf.setJpaVendorAdapter(jpaVendorAdapters());
emf.setJpaProperties(jpaProperties());
return emf;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
빈 설정 – TransactionManager
 Transaction Manager 빈 등록
 DataSourceTransactionManager vs JpaTransactionManager
JPA 설정
public interface EntityManager {
public <T> T find(Class<T> entityClass, Object primaryKey);
public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode);
public void persist(Object entity);
public <T> T merge(T entity);
public void remove(Object entity);
// ...
}
EntityManager
 엔티티(Entity)의 저장, 수정, 삭제, 조회 등 엔티티와 관련된 모든 일을 처리하는 관리자
EntityManager
EntityManagerFactory
 EntityManager를 생성하는 팩토리
 EntityManagerFactory는 애플리케이션 전체에서 하나만 생성해서 공유
EntityManagerFactory
EntityManagerFactory EntityManager(s) Entity(s)생성 관리
MyBatis to JPA
Entity
Entity
 JPA를 이용해서 데이터베이스 테이블과 매핑할 클래스
어노테이션
 @Entity: JPA가 관리할 객체임을 명시
 @Table: 매핑할 데이터베이스 테이블 이름을 명시
 @Id: 기본 키(PK) 매핑
 @Column: 필드와 칼럼을 매핑
Entity
@Entity
@Table(name = "Items")
public class ItemEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "item_id")
private Long itemId;
@Column(name = "item_name")
private String itemName;
private Long price;
}
예) Entity 설정
 ItemEntity 클래스
Entity
JPA가 관리할 객체
매핑할 테이블 이름
기본 키 매핑
필드와 칼럼 매핑
자동 생성
• TABLE 전략: 채번 테이블을 사용
• SEQUENCE 전략: 데이터베이스 시퀀스를 사용해서 기본 키를 할당 e.g.) Oracle
• IDENTITY 전략: 기본 키 생성을 데이터베이스에 위임 e.g.) MySQL
• AUTO 전략: 선택한 데이터베이스 방언(dialect)에 따라 기본 키 매핑 전략을 자동으로 선택
직접 할당
• 애플리케이션에서 직접 식별자 값을 할당
기본 키 매핑 전략
public @interface GeneratedValue {
GenerationType strategy() default AUTO;
String generator() default "";
}
public enum GenerationType {
TABLE,
SEQUENCE,
IDENTITY,
AUTO
}
@GeneratedValue
기본 키 매핑 전략
Entity
@Entity
@Table(name = "OrderItems")
public class OrderItemEntity {
@EmbeddedId
private Pk pk;
@Column
private Integer quantity;
// ...
}
예) Entity 설정
• OrderItemEntity 클래스
@Entity
@Table(name = "OrderItems")
@IdClass(OrderItemEntity.Pk.class)
public class OrderItemEntity {
@Id
@Column(name = "order_id")
private Long orderId;
@Id
@Column(name = "line_number")
private Integer lineNumber;
// ...
}
@NoArgsConstructor @AllArgsConstructor
@EqualsAndHashCode
public static class Pk implements Serializable {
private Long orderId;
private Integer lineNumber;
}
@IdClass
• Entity 클래스 레벨에서 지정
복합 키
@Entity
@Table(name = "OrderItems")
public class OrderItemEntity {
@EmbeddedId
private Pk pk;
// ...
}
@NoArgsConstructor @AllArgsConstructor
@EqualsAndHashCode
@Embeddable
public static class Pk implements Serializable {
@Column(name = "order_id")
private Long orderId;
@Column(name = "line_number")
private Integer lineNumber;
}
@EmbeddedId , @Embeddable
 @EmbeddedId: Entity 클래스의 필드에 지정
 @Embeddable: 복합 키 식별자 클래스에 지정
복합 키
@Entity
@Table(name = "Orders")
public class OrderEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "order_id")
private Long orderId;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "order_date")
private Date orderDate;
}
예) Entity 설정
 OrderEntity 클래스
Entity
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "order_date")
private Date orderDate;
public enum TemporalType {
DATE,
TIME,
TIMESTAMP
}
@Column: 객체 필드를 칼럼에 매핑
@Temporal: 날짜 타입 매핑
@Transient: 특정 필드를 칼럼에 매핑하지 않을 경우에 지정
필드와 칼럼 매핑
MyBatis to JPA
연관 관계 설정
연관 관계(association)
• 데이터베이스 테이블 간의 관계(relationship)를 엔티티 클래스의 속성(attribute)으로 모델링
• 데이터베이스 테이블은 외래 키(FK)로 JOIN을 이용해서 관계 테이블을 참조
 객체는 참조를 사용해서 연관된 객체를 참조
연관 관계 설정
외래 키(FK) 매핑
 @JoinColumn
다중성(Multiplicity)
 @OneToOne
 @OneToMany
 @ManyToOne
 @ManyToMany
연관 관계 설정
연관 관계 설정
public class OrderItemEntity {
// ...
@ManyToOne
@JoinColumn(name = "item_id")
private ItemEntity item;
}
예) 연관 관계 설정
OrderItemEntity – ItemEntity 연관 관계 설정
방향성
 단방향(unidirectional)
 양방향(bidirectional)
양방향 연관 관계
 관계의 주인(owner)
 연관 관계의 주인은 외래 키(FK)가 있는 곳
 연관 관계의 주인이 아닌 경우, mappedBy 속성으로 연관 관계의 주인을 지정
연관 관계 설정
영속성 전이
 CascadeType.ALL
 CascadeType.PERSIST
 CascadeType.MERGE
 CascadeType.REMOVE
 CascadeType.REFRESH
 CascadeType.DETACH
페치 전략(Fetch Strategy)
 FetchType.EAGER
 FetchType.LAZY
연관 관계 설정
연관 관계 설정
public class OrderEntity {
@OneToMany(
mappedBy = "order",
cascade = { CascadeType.ALL }
)
List<OrderItemEntity> orderItems = new ArrayList<>();
}
public class OrderItemEntity {
@JoinColumn(name = "order_id")
@ManyToOne(fetch = FetchType.LAZY)
private OrderEntity order;
}
예) 연관 관계 설정
OrderEntity – OrderItemEntity 연관 관계 설정
양방향
관계의 주인
영속성 전이
MyBatis to JPA
Repository
// EntityManager를 통해 entity를 저장, 수정, 삭제, 조회
ItemEntity entity1 = new ItemEntity();
entity1.setItemName("peach");
entity1.setPrice(135L);
entityManager.persist(entity1);
ItemEntity entity2 = entityManager.find(ItemEntity.class, entity1.getItemId());
entity2.setPrice(235L);
entityManager.merge(entity2);
// JPQL, Criteria API를 이용해서 복잡한 쿼리 수행
String jpql = "select item from ItemEntity item where item.itemName like '%peach%'";
List<ItemEntity> entites = entityManager.createQuery(jpql, ItemEntity.class)
.getResultList();
Spring Data Repository
 data access layer 구현을 위해 반복해서 작성했던, 유사한 코드를 줄일 수 있는 추상화 제공
Repository
public interface ItemRepository extends JpaRepository<ItemEntity, Long> {
}
예) Repository 설정
 ItemRepository interface
 JpaRepository interface 상속
Repository
웬만한 CRUD, Pagination, Sorting 관련 메서드 제공
JpaRepository
// insert / update
<S extends T> S save(S entity);
// select * from Items where item_id = {id}
T findOne(ID id);
// select count(*) from Items;
long count();
// delete from Items where item_id = {id}
void delete(ID id);
// ...
JpaRepository가 제공하는 메서드들이 실제 수행하는 쿼리
Repository
메서드 이름으로 쿼리 생성
public interface ItemRepository … {
// select * from Items where item_name like '%{itemName}%'
ItemEntity findByItemNameLike(String itemName);
// select item_id from Items where item_name = '{itemName}'
// and price = {price} limit 1
boolean existsByItemNameAndPrice(String itemName, Long price);
// select count(*) from Items where item_name like '%{itemName}%'
int countByItemNameLike(String itemName);
// delete from Items where price between {price1} and {price2}
void deleteByPriceBetween(long price1, long price2);
}
Spring Data JPA에서 제공하는 기능으로 이름 규칙에 맞춰 interface에 선언하면 쿼리 생성
cf.) https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords
JPA에서 제공하는 객체 지향 쿼리
 JPQL: 엔티티 객체를 조회하는 객체 지향 쿼리
 Criteria API: JPQL을 생성하는 빌더 클래스
third party library를 이용하는 방법
 Querydsl
 jOOQ
 …
복잡한 쿼리 작성
MyBatis to JPA
애플리케이션에서의 사용
public class ItemService {
@Autowired
private ItemRepository itemRepository;
@Transactional
public Item createItem(Item item) {
ItemEntity itemEntity = new ItemEntity();
itemEntity.setItemName(item.getItemName());
itemEntity.setPrice(item.getPrice());
ItemEntity newItem = itemRepository.save(itemEntity);
return newItem.toItemDto();
}
}
ItemService – insert
애플리케이션에서의 사용
애플리케이션에서의 사용
public class ItemService {
@Autowired
private ItemRepository itemRepository;
@Transactional
public Item createItem(Item item) {
ItemEntity itemEntity = new ItemEntity();
itemEntity.setItemName(item.getItemName());
itemEntity.setPrice(item.getPrice());
ItemEntity newItem
= itemRepository.save(itemEntity);
return newItem.toItemDto();
}
}
ItemService – insert vs MyBatis
VS
public class ItemService {
@Transactional
public Item updateItem(Item item) {
ItemEntity itemEntity = new ItemEntity();
itemEntity.setItemId(item.getItemId());
itemEntity.setItemName(item.getItemName());
itemEntity.setPrice(item.getPrice());
ItemEntity newItemEntity = itemRepository.save(itemEntity);
return newItemEntity.toItemDto();
}
}
ItemService – update
애플리케이션에서의 사용
애플리케이션에서의 사용
public class ItemService {
@Transactional
public Item updateItem(Item item) {
ItemEntity itemEntity = new ItemEntity();
itemEntity.setItemId(item.getItemId());
itemEntity.setItemName(item.getItemName());
itemEntity.setPrice(item.getPrice());
ItemEntity newItemEntity
= itemRepository.save(itemEntity);
return newItemEntity.toItemDto();
}
}
ItemService – update vs MyBatis
VS
public class ItemService {
@Transactional
public boolean deleteItem(Long itemId) {
itemRepository.delete(itemId);
return true;
}
}
ItemService – delete
애플리케이션에서의 사용
애플리케이션에서의 사용
public class ItemService {
@Transactional
public boolean deleteItem(Long itemId) {
itemRepository.delete(itemId);
return true;
}
}
ItemService – delete vs MyBatis
VS
ItemService – pagination 구현
 Spring Data JPA에서 제공하는 Pageable 사용
애플리케이션에서의 사용
public interface Pageable {
int getPageNumber();
int getPageSize();
int getOffset();
Sort getSort();
Pageable next();
Pageable previousOrFirst();
Pageable first();
boolean hasPrevious();
}
Spring Data 프로젝트에서 제공하는 web support 기능 중 하나
 Pageable: pagination 정보를 추상화한 인터페이스
Pageable
@RestController
@RequestMapping("/items")
public class ItemController {
@Autowired
ItemService itemService;
@GetMapping("")
public List<Item> getItems(Pageable pageable) {
return itemService.getItems(pageable);
}
}
ItemController – Pageable 적용
 Spring Data에서 page, size 파라미터값을 Controller의 Pageable 인자로 변환해서 전달
애플리케이션에서의 사용
GET /items?page=0&size=30
public class ItemService {
public List<Item> getItems(Pageable pageable) {
Page<ItemEntity> itemPage = itemRepository.findAll(pageable);
return itemPage.getContent()
.stream()
.map(ItemEntity::toItemDto)
.collect(Collectors.toList());
}
}
ItemService – pagination 구현
 JpaRepository.findAll(Pageable pageable) 메서드로 Pageable 객체를 전달
애플리케이션에서의 사용
public class OrderService {
@Transactional
public Order createOrder(Order order) {
OrderEntity orderEntity = new OrderEntity();
orderEntity.setOrderDate(new Date());
order.getOrderItems()
.forEach(orderItem -> {
ItemEntity itemEntity = new ItemEntity();
itemEntity.setItemId(orderItem.getItem().getItemId());
OrderItemEntity orderItemEntity = new OrderItemEntity();
orderItemEntity.setOrder(orderEntity);
orderItemEntity.getPk().setLineNumber(orderItem.getLineNumber());
orderItemEntity.setItem(itemEntity);
orderItemEntity.setQuantity(orderItem.getQuantity());
orderEntity.getOrderItems().add(orderItemEntity);
});
OrderEntity newEntity = orderRepository.save(orderEntity);
return newEntity.toOrderDto();
}
}
OrderService – insert
 영속성 전이를 이용해서 OrderEntity를 저장할 때 OrderItemEntity도 함께 저장
애플리케이션에서의 사용
애플리케이션에서의 사용
public class OrderService {
@Transactional
public Order createOrder(Order order) {
OrderEntity orderEntity = new OrderEntity();
orderEntity.setOrderDate(new Date());
order.getOrderItems()
.forEach(orderItem -> {
ItemEntity itemEntity = new ItemEntity();
itemEntity.setItemId(orderItem.getItem().getItemId());
OrderItemEntity orderItemEntity = new OrderItemEntity();
orderItemEntity.setOrder(orderEntity);
orderItemEntity.getPk().setLineNumber(orderItem.getLineNumber());
orderItemEntity.setItem(itemEntity);
orderItemEntity.setQuantity(orderItem.getQuantity());
orderEntity.getOrderItems().add(orderItemEntity);
});
OrderEntity newEntity = orderRepository.save(orderEntity);
return newEntity.toOrderDto();
}
}
OrderService – insert vs MyBatis
VS
 JPA 설정
 spring-data-jpa, hibernate-entitymanager 의존성 라이브러리 추가
 EntityManagerFactoryBean, JpaTransactionManager 빈 등록
 Entity 설정
 @Entity, @Table, @Id, @Column, @Temporal, @GeneratedValue, @EmbeddedId, …
 연관 관계 설정
 @JoinColumn, @OneToMany, @ManyToOne, mappedBy, FetchType.LAZY, …
 Repository interface 생성 - JpaRepository 상속
 애플리케이션에서의 사용 – Entity, Repository, Pageable, …
MyBatis to JPA Summary
 상대적으로 높은 학습 곡선
 But,
 기술적인 진입 장벽을 낮춰줄 여러 솔루션들이 존재(e.g. Spring Data JPA, QueryDSL 등)
 2015년 이후로 JPA 관련 다양한 국내 서적이 출간된 상태
 JPQL에는 분명 한계가 있다
 But,
 Native SQL
 다른 Data Access 기술과 혼용 및 분리(CQRS) 가능
 그럼에도 불구하고 …
JPA의 단점
그 동안 MyBatis로 마이 버팃으면
이제는 JPA를 한 번 써 봐야 할 때
MyBatis에서 JPA로!
© 2018 NHN FORWARD. All rights reserved.
THANK YOU
© 2018 NHN FORWARD. All rights reserved.
Q&A

More Related Content

What's hot

Advanced Reflection in Java
Advanced Reflection in JavaAdvanced Reflection in Java
Advanced Reflection in Javakim.mens
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentationJohn Slick
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해beom kyun choi
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSRafael Casuso Romate
 
[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱
[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱
[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱PgDay.Seoul
 
Memory Management: What You Need to Know When Moving to Java 8
Memory Management: What You Need to Know When Moving to Java 8Memory Management: What You Need to Know When Moving to Java 8
Memory Management: What You Need to Know When Moving to Java 8AppDynamics
 
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정PgDay.Seoul
 
Spring - Part 2 - Autowiring, Annotations, Java based Configuration - slides
Spring - Part 2 - Autowiring, Annotations, Java based Configuration - slidesSpring - Part 2 - Autowiring, Annotations, Java based Configuration - slides
Spring - Part 2 - Autowiring, Annotations, Java based Configuration - slidesHitesh-Java
 
Clean backends with NestJs
Clean backends with NestJsClean backends with NestJs
Clean backends with NestJsAymene Bennour
 
애플리케이션 아키텍처와 객체지향
애플리케이션 아키텍처와 객체지향 애플리케이션 아키텍처와 객체지향
애플리케이션 아키텍처와 객체지향 Young-Ho Cho
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithVictor Rentea
 
Design by contract(계약에의한설계)
Design by contract(계약에의한설계)Design by contract(계약에의한설계)
Design by contract(계약에의한설계)Jeong-gyu Kim
 
우아한 모노리스
우아한 모노리스우아한 모노리스
우아한 모노리스Arawn Park
 
JDBC - JPA - Spring Data
JDBC - JPA - Spring DataJDBC - JPA - Spring Data
JDBC - JPA - Spring DataArturs Drozdovs
 
オープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについて
オープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについてオープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについて
オープンソースで提供される第二のJVM:OpenJ9 VMとIBM JavaについてTakakiyo Tanaka
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
Spring Security
Spring SecuritySpring Security
Spring SecurityBoy Tech
 

What's hot (20)

Advanced Reflection in Java
Advanced Reflection in JavaAdvanced Reflection in Java
Advanced Reflection in Java
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
 
[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱
[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱
[pgday.Seoul 2022] POSTGRES 테스트코드로 기여하기 - 이동욱
 
Spring boot jpa
Spring boot jpaSpring boot jpa
Spring boot jpa
 
Memory Management: What You Need to Know When Moving to Java 8
Memory Management: What You Need to Know When Moving to Java 8Memory Management: What You Need to Know When Moving to Java 8
Memory Management: What You Need to Know When Moving to Java 8
 
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
 
Spring - Part 2 - Autowiring, Annotations, Java based Configuration - slides
Spring - Part 2 - Autowiring, Annotations, Java based Configuration - slidesSpring - Part 2 - Autowiring, Annotations, Java based Configuration - slides
Spring - Part 2 - Autowiring, Annotations, Java based Configuration - slides
 
Clean backends with NestJs
Clean backends with NestJsClean backends with NestJs
Clean backends with NestJs
 
애플리케이션 아키텍처와 객체지향
애플리케이션 아키텍처와 객체지향 애플리케이션 아키텍처와 객체지향
애플리케이션 아키텍처와 객체지향
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a Monolith
 
Design by contract(계약에의한설계)
Design by contract(계약에의한설계)Design by contract(계약에의한설계)
Design by contract(계약에의한설계)
 
우아한 모노리스
우아한 모노리스우아한 모노리스
우아한 모노리스
 
JDBC - JPA - Spring Data
JDBC - JPA - Spring DataJDBC - JPA - Spring Data
JDBC - JPA - Spring Data
 
オープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについて
オープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについてオープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについて
オープンソースで提供される第二のJVM:OpenJ9 VMとIBM Javaについて
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Introduction à JPA (Java Persistence API )
Introduction à JPA  (Java Persistence API )Introduction à JPA  (Java Persistence API )
Introduction à JPA (Java Persistence API )
 
Spring Security
Spring SecuritySpring Security
Spring Security
 

Similar to [2018] MyBatis에서 JPA로

MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로Dongmin Shin
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3plusperson
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
Jlook open api platform-appdevguide
Jlook open api platform-appdevguideJlook open api platform-appdevguide
Jlook open api platform-appdevguideHongSeong Jeon
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발NAVER D2
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기경원 이
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3plusperson
 
Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Younghan Kim
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술NAVER D2
 
Software Architect day - 웹 프레임워크 종결 - metaworks3
Software Architect day - 웹 프레임워크 종결 -  metaworks3Software Architect day - 웹 프레임워크 종결 -  metaworks3
Software Architect day - 웹 프레임워크 종결 - metaworks3uEngine Solutions
 
2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료
2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료
2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료beom kyun choi
 
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?JaewonLee153
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA경원 이
 

Similar to [2018] MyBatis에서 JPA로 (20)

MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로
 
Java JPA
Java JPAJava JPA
Java JPA
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
Jlook open api platform-appdevguide
Jlook open api platform-appdevguideJlook open api platform-appdevguide
Jlook open api platform-appdevguide
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발
 
Swt J Face 2/3
Swt J Face 2/3Swt J Face 2/3
Swt J Face 2/3
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3
 
Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리
 
Srping data rest
Srping data restSrping data rest
Srping data rest
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술
 
Software Architect day - 웹 프레임워크 종결 - metaworks3
Software Architect day - 웹 프레임워크 종결 -  metaworks3Software Architect day - 웹 프레임워크 종결 -  metaworks3
Software Architect day - 웹 프레임워크 종결 - metaworks3
 
Hibernate 기초
Hibernate 기초Hibernate 기초
Hibernate 기초
 
2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료
2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료
2007년 제8회 JCO 컨퍼런스 POJO 프로그래밍 발표 자료
 
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA
 

More from NHN FORWARD

[2019] 패션 시소러스 기반 상품 특징 분석 시스템
[2019] 패션 시소러스 기반 상품 특징 분석 시스템[2019] 패션 시소러스 기반 상품 특징 분석 시스템
[2019] 패션 시소러스 기반 상품 특징 분석 시스템NHN FORWARD
 
[2019] 스몰 스텝: Android 렛츠기릿!
[2019] 스몰 스텝: Android 렛츠기릿![2019] 스몰 스텝: Android 렛츠기릿!
[2019] 스몰 스텝: Android 렛츠기릿!NHN FORWARD
 
딥러닝, 야 너도 할 수 있어(feat. PyTorch)
딥러닝, 야 너도 할 수 있어(feat. PyTorch)딥러닝, 야 너도 할 수 있어(feat. PyTorch)
딥러닝, 야 너도 할 수 있어(feat. PyTorch)NHN FORWARD
 
NHN 베이스캠프: 신입사원들은 무엇을 배우나요?
NHN 베이스캠프: 신입사원들은 무엇을 배우나요?NHN 베이스캠프: 신입사원들은 무엇을 배우나요?
NHN 베이스캠프: 신입사원들은 무엇을 배우나요?NHN FORWARD
 
[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기
[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기
[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기NHN FORWARD
 
[2019] 전기 먹는 하마의 다이어트 성공기 클라우드 데이터 센터의 에너지 절감 노력과 사례
[2019] 전기 먹는 하마의 다이어트 성공기   클라우드 데이터 센터의 에너지 절감 노력과 사례[2019] 전기 먹는 하마의 다이어트 성공기   클라우드 데이터 센터의 에너지 절감 노력과 사례
[2019] 전기 먹는 하마의 다이어트 성공기 클라우드 데이터 센터의 에너지 절감 노력과 사례NHN FORWARD
 
[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)
[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)
[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)NHN FORWARD
 
[2019] 아직도 돈 주고 DB 쓰나요? for Developer
[2019] 아직도 돈 주고 DB 쓰나요? for Developer[2019] 아직도 돈 주고 DB 쓰나요? for Developer
[2019] 아직도 돈 주고 DB 쓰나요? for DeveloperNHN FORWARD
 
[2019] 아직도 돈 주고 DB 쓰나요 for DBA
[2019] 아직도 돈 주고 DB 쓰나요 for DBA[2019] 아직도 돈 주고 DB 쓰나요 for DBA
[2019] 아직도 돈 주고 DB 쓰나요 for DBANHN FORWARD
 
[2019] 비주얼 브랜딩: Basic system
[2019] 비주얼 브랜딩: Basic system[2019] 비주얼 브랜딩: Basic system
[2019] 비주얼 브랜딩: Basic systemNHN FORWARD
 
[2019] PAYCO 매거진 서버 Kotlin 적용기
[2019] PAYCO 매거진 서버 Kotlin 적용기[2019] PAYCO 매거진 서버 Kotlin 적용기
[2019] PAYCO 매거진 서버 Kotlin 적용기NHN FORWARD
 
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)NHN FORWARD
 
[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기
[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기
[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기NHN FORWARD
 
[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기
[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기
[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기NHN FORWARD
 
[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례
[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례
[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례NHN FORWARD
 
[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자
[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자
[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자NHN FORWARD
 
[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩NHN FORWARD
 
[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션
[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션
[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션NHN FORWARD
 
[2019] 글로벌 게임 서비스 노하우
[2019] 글로벌 게임 서비스 노하우[2019] 글로벌 게임 서비스 노하우
[2019] 글로벌 게임 서비스 노하우NHN FORWARD
 
[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인
[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인
[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인NHN FORWARD
 

More from NHN FORWARD (20)

[2019] 패션 시소러스 기반 상품 특징 분석 시스템
[2019] 패션 시소러스 기반 상품 특징 분석 시스템[2019] 패션 시소러스 기반 상품 특징 분석 시스템
[2019] 패션 시소러스 기반 상품 특징 분석 시스템
 
[2019] 스몰 스텝: Android 렛츠기릿!
[2019] 스몰 스텝: Android 렛츠기릿![2019] 스몰 스텝: Android 렛츠기릿!
[2019] 스몰 스텝: Android 렛츠기릿!
 
딥러닝, 야 너도 할 수 있어(feat. PyTorch)
딥러닝, 야 너도 할 수 있어(feat. PyTorch)딥러닝, 야 너도 할 수 있어(feat. PyTorch)
딥러닝, 야 너도 할 수 있어(feat. PyTorch)
 
NHN 베이스캠프: 신입사원들은 무엇을 배우나요?
NHN 베이스캠프: 신입사원들은 무엇을 배우나요?NHN 베이스캠프: 신입사원들은 무엇을 배우나요?
NHN 베이스캠프: 신입사원들은 무엇을 배우나요?
 
[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기
[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기
[2019] GIF 스티커 만들기: 스파인 2D를 이용한 움직이는 스티커 만들기
 
[2019] 전기 먹는 하마의 다이어트 성공기 클라우드 데이터 센터의 에너지 절감 노력과 사례
[2019] 전기 먹는 하마의 다이어트 성공기   클라우드 데이터 센터의 에너지 절감 노력과 사례[2019] 전기 먹는 하마의 다이어트 성공기   클라우드 데이터 센터의 에너지 절감 노력과 사례
[2019] 전기 먹는 하마의 다이어트 성공기 클라우드 데이터 센터의 에너지 절감 노력과 사례
 
[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)
[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)
[2019] 스몰 스텝: Dooray!를 이용한 업무 효율화/자동화(고객문의 시스템 구축)
 
[2019] 아직도 돈 주고 DB 쓰나요? for Developer
[2019] 아직도 돈 주고 DB 쓰나요? for Developer[2019] 아직도 돈 주고 DB 쓰나요? for Developer
[2019] 아직도 돈 주고 DB 쓰나요? for Developer
 
[2019] 아직도 돈 주고 DB 쓰나요 for DBA
[2019] 아직도 돈 주고 DB 쓰나요 for DBA[2019] 아직도 돈 주고 DB 쓰나요 for DBA
[2019] 아직도 돈 주고 DB 쓰나요 for DBA
 
[2019] 비주얼 브랜딩: Basic system
[2019] 비주얼 브랜딩: Basic system[2019] 비주얼 브랜딩: Basic system
[2019] 비주얼 브랜딩: Basic system
 
[2019] PAYCO 매거진 서버 Kotlin 적용기
[2019] PAYCO 매거진 서버 Kotlin 적용기[2019] PAYCO 매거진 서버 Kotlin 적용기
[2019] PAYCO 매거진 서버 Kotlin 적용기
 
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
 
[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기
[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기
[2019] Java에서 Fiber를 이용하여 동시성concurrency 프로그래밍 쉽게 하기
 
[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기
[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기
[2019] PAYCO 쇼핑 마이크로서비스 아키텍처(MSA) 전환기
 
[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례
[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례
[2019] 비식별 데이터로부터의 가치 창출과 수익화 사례
 
[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자
[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자
[2019] 게임 서버 대규모 부하 테스트와 모니터링 이렇게 해보자
 
[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩[2019] 200만 동접 게임을 위한 MySQL 샤딩
[2019] 200만 동접 게임을 위한 MySQL 샤딩
 
[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션
[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션
[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션
 
[2019] 글로벌 게임 서비스 노하우
[2019] 글로벌 게임 서비스 노하우[2019] 글로벌 게임 서비스 노하우
[2019] 글로벌 게임 서비스 노하우
 
[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인
[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인
[2019] 배틀로얄 전장(map) 제작으로 알아보는 슈팅 게임 레벨 디자인
 

[2018] MyBatis에서 JPA로

  • 1. © 2018 NHN FORWARD. All rights reserved. MyBatis에서 JPA로 신동민 Dooray개발실
  • 2. CONTENTS 1. Why MyBatis? 2. Why JPA? 3. What is JPA? 4. MyBatis to JPA
  • 3. 최근 5년간 구글 트렌드 MyBatis vs JPA(전 세계)
  • 4. 최근 5년간 구글 트렌드 MyBatis vs JPA(전 세계) MyBatis < JPA
  • 5. 최근 5년간 구글 트렌드 MyBatis vs JPA – 지역별(전 세계)
  • 6. 최근 5년간 구글 트렌드 MyBatis vs JPA(한국)
  • 7. 최근 5년간 구글 트렌드 MyBatis vs JPA(한국) MyBatis ≥ JPA
  • 8. 그 동안 MyBatis로 마이 버팃으면 이제는 JPA를 한 번 써 봐야 할 때 MyBatis에서 JPA로!
  • 10. JDBC를 좀더 편하게 사용할 수 있도록 객체를 SQL이나 저장 프로시저와 매핑해주는 퍼시스턴스 프레임워크 (persistence framework) 한 마디로, SQL Mapper MyBatis
  • 11.  다른 프레임워크들에 비해 간단하다 (Simple)  소스 코드와 SQL의 분리(생산성, 작업 분배)  SQL을 직접 다룰 수 있다(복잡한 쿼리, 함수, 저장 프로시저 등) MyBatis의 장점
  • 12. MyBatis in 2010 NEW HOME OF THE WORLD’S MOST POPULAR SQL MAPPING FRAMEWORK
  • 13.
  • 15. REST API MyBatis 예제 프로그램
  • 17.  반복적인 코드와 CRUD SQL 작업  SQL과 데이터베이스 벤더에 대한 종속성 MyBatis의 단점
  • 19. 생산성  JPA를 사용하면 지루하고 반복적인 CRUD용 SQL을 개발자가 직접 작성하지 않아도 된다  Spring Data JPA를 사용하면 interface 선언만으로도 쿼리 구현이 가능하기 때문에 관리 도구 등에서 가볍게 사용할 수 있는 CRUD 쿼리를 손쉽게 대처할 수 있다 JPA를 사용해야 하는 이유 구분 Order Item OrderItem insert insert into Orders ( … ) insert into Items ( … ) insert into OrderItems ( …) update update Orders set … update Items set … update OrderItems set … delete delete from Orders … delete from Items … delete from OrderItems … … … … …
  • 20. JPA를 사용해야 하는 이유 public class Item { private Long itemId; private String itemName; private Long price; private String category; } 유지보수  칼럼 추가/삭제 시 직접 관련된 CRUD 쿼리를 모두 수정하는 대신 JPA가 관리하는 모델(Entity)을 수정하면 된다 구분 Item insert insert into Items ( item_id, item_name, price, category ) update update Items set item_name = ‘’, price = 0, category = ‘’ select select item_id, item_name, price, category from Items … … …
  • 21. 데이터 접근 추상화와 벤더 독립성  데이터베이스 벤더마다 미묘하게 다른 데이터 타입이나 SQL을 JPA를 이용하면 손쉽게 해결할 수 있다 JPA를 사용해야 하는 이유 Oracle MySql
  • 22. SQL 중심적인 개발에서 객체 중심으로 개발 패러다임 불일치 해결  JPA는 객체와 관계형 데이터베이스 사이의 패러다임의 불일치로 발생하는 문제를 해결  (상속, 연관 관계, 객체 그래프 탐색 등) JPA를 사용해야 하는 이유
  • 24. JPA Java Persistence API  자바 진영의 ORM 기술 표준 ORM(Object-Relational Mapping)  데이터베이스 객체를 자바 객체로 매핑하여 객체 간의 관계를 바탕으로 SQL을 자동으로 생성
  • 25. JPA  표준 명세  JSR 338 – Java Persistence 2.2 Hibernate  JPA 실제 구현체 : Hibernate, EclipseLink, DataNuclues  Hibernate가 사실상 표준(de facto) JPA, Hibernate
  • 26. Spring Data  다양한 데이터 저장소에 대한 접근을 추상화하기 위한 Spring 프로젝트  JPA, JDBC, Redis, MongoDB, Elasticsearch 등 Spring Data JPA  Repository 추상화를 통해 interface 선언만으로도 구현 가능  메서드 이름으로 쿼리 생성  Web Support(페이징, 정렬, 도메인 클래스 컨버터 등) Spring Data JPA
  • 30. 빈 설정 – EntityManagerFactory  LocalContainerEntityManagerFactoryBean 빈 등록  SqlSessionFactoryBean vs EntityManagerFactoryBean JPA 설정 @Bean LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource); emf.setPackagesToScan("com.nhnent.forward.mybatistojpa.entity"); emf.setJpaVendorAdapter(jpaVendorAdapters()); emf.setJpaProperties(jpaProperties()); return emf; }
  • 31. @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } 빈 설정 – TransactionManager  Transaction Manager 빈 등록  DataSourceTransactionManager vs JpaTransactionManager JPA 설정
  • 32. public interface EntityManager { public <T> T find(Class<T> entityClass, Object primaryKey); public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode); public void persist(Object entity); public <T> T merge(T entity); public void remove(Object entity); // ... } EntityManager  엔티티(Entity)의 저장, 수정, 삭제, 조회 등 엔티티와 관련된 모든 일을 처리하는 관리자 EntityManager
  • 33. EntityManagerFactory  EntityManager를 생성하는 팩토리  EntityManagerFactory는 애플리케이션 전체에서 하나만 생성해서 공유 EntityManagerFactory EntityManagerFactory EntityManager(s) Entity(s)생성 관리
  • 35. Entity  JPA를 이용해서 데이터베이스 테이블과 매핑할 클래스 어노테이션  @Entity: JPA가 관리할 객체임을 명시  @Table: 매핑할 데이터베이스 테이블 이름을 명시  @Id: 기본 키(PK) 매핑  @Column: 필드와 칼럼을 매핑 Entity
  • 36. @Entity @Table(name = "Items") public class ItemEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "item_id") private Long itemId; @Column(name = "item_name") private String itemName; private Long price; } 예) Entity 설정  ItemEntity 클래스 Entity JPA가 관리할 객체 매핑할 테이블 이름 기본 키 매핑 필드와 칼럼 매핑
  • 37. 자동 생성 • TABLE 전략: 채번 테이블을 사용 • SEQUENCE 전략: 데이터베이스 시퀀스를 사용해서 기본 키를 할당 e.g.) Oracle • IDENTITY 전략: 기본 키 생성을 데이터베이스에 위임 e.g.) MySQL • AUTO 전략: 선택한 데이터베이스 방언(dialect)에 따라 기본 키 매핑 전략을 자동으로 선택 직접 할당 • 애플리케이션에서 직접 식별자 값을 할당 기본 키 매핑 전략
  • 38. public @interface GeneratedValue { GenerationType strategy() default AUTO; String generator() default ""; } public enum GenerationType { TABLE, SEQUENCE, IDENTITY, AUTO } @GeneratedValue 기본 키 매핑 전략
  • 39. Entity @Entity @Table(name = "OrderItems") public class OrderItemEntity { @EmbeddedId private Pk pk; @Column private Integer quantity; // ... } 예) Entity 설정 • OrderItemEntity 클래스
  • 40. @Entity @Table(name = "OrderItems") @IdClass(OrderItemEntity.Pk.class) public class OrderItemEntity { @Id @Column(name = "order_id") private Long orderId; @Id @Column(name = "line_number") private Integer lineNumber; // ... } @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode public static class Pk implements Serializable { private Long orderId; private Integer lineNumber; } @IdClass • Entity 클래스 레벨에서 지정 복합 키
  • 41. @Entity @Table(name = "OrderItems") public class OrderItemEntity { @EmbeddedId private Pk pk; // ... } @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @Embeddable public static class Pk implements Serializable { @Column(name = "order_id") private Long orderId; @Column(name = "line_number") private Integer lineNumber; } @EmbeddedId , @Embeddable  @EmbeddedId: Entity 클래스의 필드에 지정  @Embeddable: 복합 키 식별자 클래스에 지정 복합 키
  • 42. @Entity @Table(name = "Orders") public class OrderEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "order_id") private Long orderId; @Temporal(TemporalType.TIMESTAMP) @Column(name = "order_date") private Date orderDate; } 예) Entity 설정  OrderEntity 클래스 Entity
  • 43. @Temporal(TemporalType.TIMESTAMP) @Column(name = "order_date") private Date orderDate; public enum TemporalType { DATE, TIME, TIMESTAMP } @Column: 객체 필드를 칼럼에 매핑 @Temporal: 날짜 타입 매핑 @Transient: 특정 필드를 칼럼에 매핑하지 않을 경우에 지정 필드와 칼럼 매핑
  • 44. MyBatis to JPA 연관 관계 설정
  • 45. 연관 관계(association) • 데이터베이스 테이블 간의 관계(relationship)를 엔티티 클래스의 속성(attribute)으로 모델링 • 데이터베이스 테이블은 외래 키(FK)로 JOIN을 이용해서 관계 테이블을 참조  객체는 참조를 사용해서 연관된 객체를 참조 연관 관계 설정
  • 46. 외래 키(FK) 매핑  @JoinColumn 다중성(Multiplicity)  @OneToOne  @OneToMany  @ManyToOne  @ManyToMany 연관 관계 설정
  • 47. 연관 관계 설정 public class OrderItemEntity { // ... @ManyToOne @JoinColumn(name = "item_id") private ItemEntity item; } 예) 연관 관계 설정 OrderItemEntity – ItemEntity 연관 관계 설정
  • 48. 방향성  단방향(unidirectional)  양방향(bidirectional) 양방향 연관 관계  관계의 주인(owner)  연관 관계의 주인은 외래 키(FK)가 있는 곳  연관 관계의 주인이 아닌 경우, mappedBy 속성으로 연관 관계의 주인을 지정 연관 관계 설정
  • 49. 영속성 전이  CascadeType.ALL  CascadeType.PERSIST  CascadeType.MERGE  CascadeType.REMOVE  CascadeType.REFRESH  CascadeType.DETACH 페치 전략(Fetch Strategy)  FetchType.EAGER  FetchType.LAZY 연관 관계 설정
  • 50. 연관 관계 설정 public class OrderEntity { @OneToMany( mappedBy = "order", cascade = { CascadeType.ALL } ) List<OrderItemEntity> orderItems = new ArrayList<>(); } public class OrderItemEntity { @JoinColumn(name = "order_id") @ManyToOne(fetch = FetchType.LAZY) private OrderEntity order; } 예) 연관 관계 설정 OrderEntity – OrderItemEntity 연관 관계 설정 양방향 관계의 주인 영속성 전이
  • 52. // EntityManager를 통해 entity를 저장, 수정, 삭제, 조회 ItemEntity entity1 = new ItemEntity(); entity1.setItemName("peach"); entity1.setPrice(135L); entityManager.persist(entity1); ItemEntity entity2 = entityManager.find(ItemEntity.class, entity1.getItemId()); entity2.setPrice(235L); entityManager.merge(entity2); // JPQL, Criteria API를 이용해서 복잡한 쿼리 수행 String jpql = "select item from ItemEntity item where item.itemName like '%peach%'"; List<ItemEntity> entites = entityManager.createQuery(jpql, ItemEntity.class) .getResultList(); Spring Data Repository  data access layer 구현을 위해 반복해서 작성했던, 유사한 코드를 줄일 수 있는 추상화 제공 Repository
  • 53. public interface ItemRepository extends JpaRepository<ItemEntity, Long> { } 예) Repository 설정  ItemRepository interface  JpaRepository interface 상속 Repository
  • 54. 웬만한 CRUD, Pagination, Sorting 관련 메서드 제공 JpaRepository
  • 55. // insert / update <S extends T> S save(S entity); // select * from Items where item_id = {id} T findOne(ID id); // select count(*) from Items; long count(); // delete from Items where item_id = {id} void delete(ID id); // ... JpaRepository가 제공하는 메서드들이 실제 수행하는 쿼리 Repository
  • 56. 메서드 이름으로 쿼리 생성 public interface ItemRepository … { // select * from Items where item_name like '%{itemName}%' ItemEntity findByItemNameLike(String itemName); // select item_id from Items where item_name = '{itemName}' // and price = {price} limit 1 boolean existsByItemNameAndPrice(String itemName, Long price); // select count(*) from Items where item_name like '%{itemName}%' int countByItemNameLike(String itemName); // delete from Items where price between {price1} and {price2} void deleteByPriceBetween(long price1, long price2); } Spring Data JPA에서 제공하는 기능으로 이름 규칙에 맞춰 interface에 선언하면 쿼리 생성 cf.) https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords
  • 57. JPA에서 제공하는 객체 지향 쿼리  JPQL: 엔티티 객체를 조회하는 객체 지향 쿼리  Criteria API: JPQL을 생성하는 빌더 클래스 third party library를 이용하는 방법  Querydsl  jOOQ  … 복잡한 쿼리 작성
  • 59. public class ItemService { @Autowired private ItemRepository itemRepository; @Transactional public Item createItem(Item item) { ItemEntity itemEntity = new ItemEntity(); itemEntity.setItemName(item.getItemName()); itemEntity.setPrice(item.getPrice()); ItemEntity newItem = itemRepository.save(itemEntity); return newItem.toItemDto(); } } ItemService – insert 애플리케이션에서의 사용
  • 60. 애플리케이션에서의 사용 public class ItemService { @Autowired private ItemRepository itemRepository; @Transactional public Item createItem(Item item) { ItemEntity itemEntity = new ItemEntity(); itemEntity.setItemName(item.getItemName()); itemEntity.setPrice(item.getPrice()); ItemEntity newItem = itemRepository.save(itemEntity); return newItem.toItemDto(); } } ItemService – insert vs MyBatis VS
  • 61. public class ItemService { @Transactional public Item updateItem(Item item) { ItemEntity itemEntity = new ItemEntity(); itemEntity.setItemId(item.getItemId()); itemEntity.setItemName(item.getItemName()); itemEntity.setPrice(item.getPrice()); ItemEntity newItemEntity = itemRepository.save(itemEntity); return newItemEntity.toItemDto(); } } ItemService – update 애플리케이션에서의 사용
  • 62. 애플리케이션에서의 사용 public class ItemService { @Transactional public Item updateItem(Item item) { ItemEntity itemEntity = new ItemEntity(); itemEntity.setItemId(item.getItemId()); itemEntity.setItemName(item.getItemName()); itemEntity.setPrice(item.getPrice()); ItemEntity newItemEntity = itemRepository.save(itemEntity); return newItemEntity.toItemDto(); } } ItemService – update vs MyBatis VS
  • 63. public class ItemService { @Transactional public boolean deleteItem(Long itemId) { itemRepository.delete(itemId); return true; } } ItemService – delete 애플리케이션에서의 사용
  • 64. 애플리케이션에서의 사용 public class ItemService { @Transactional public boolean deleteItem(Long itemId) { itemRepository.delete(itemId); return true; } } ItemService – delete vs MyBatis VS
  • 65. ItemService – pagination 구현  Spring Data JPA에서 제공하는 Pageable 사용 애플리케이션에서의 사용
  • 66. public interface Pageable { int getPageNumber(); int getPageSize(); int getOffset(); Sort getSort(); Pageable next(); Pageable previousOrFirst(); Pageable first(); boolean hasPrevious(); } Spring Data 프로젝트에서 제공하는 web support 기능 중 하나  Pageable: pagination 정보를 추상화한 인터페이스 Pageable
  • 67. @RestController @RequestMapping("/items") public class ItemController { @Autowired ItemService itemService; @GetMapping("") public List<Item> getItems(Pageable pageable) { return itemService.getItems(pageable); } } ItemController – Pageable 적용  Spring Data에서 page, size 파라미터값을 Controller의 Pageable 인자로 변환해서 전달 애플리케이션에서의 사용 GET /items?page=0&size=30
  • 68. public class ItemService { public List<Item> getItems(Pageable pageable) { Page<ItemEntity> itemPage = itemRepository.findAll(pageable); return itemPage.getContent() .stream() .map(ItemEntity::toItemDto) .collect(Collectors.toList()); } } ItemService – pagination 구현  JpaRepository.findAll(Pageable pageable) 메서드로 Pageable 객체를 전달 애플리케이션에서의 사용
  • 69. public class OrderService { @Transactional public Order createOrder(Order order) { OrderEntity orderEntity = new OrderEntity(); orderEntity.setOrderDate(new Date()); order.getOrderItems() .forEach(orderItem -> { ItemEntity itemEntity = new ItemEntity(); itemEntity.setItemId(orderItem.getItem().getItemId()); OrderItemEntity orderItemEntity = new OrderItemEntity(); orderItemEntity.setOrder(orderEntity); orderItemEntity.getPk().setLineNumber(orderItem.getLineNumber()); orderItemEntity.setItem(itemEntity); orderItemEntity.setQuantity(orderItem.getQuantity()); orderEntity.getOrderItems().add(orderItemEntity); }); OrderEntity newEntity = orderRepository.save(orderEntity); return newEntity.toOrderDto(); } } OrderService – insert  영속성 전이를 이용해서 OrderEntity를 저장할 때 OrderItemEntity도 함께 저장 애플리케이션에서의 사용
  • 70. 애플리케이션에서의 사용 public class OrderService { @Transactional public Order createOrder(Order order) { OrderEntity orderEntity = new OrderEntity(); orderEntity.setOrderDate(new Date()); order.getOrderItems() .forEach(orderItem -> { ItemEntity itemEntity = new ItemEntity(); itemEntity.setItemId(orderItem.getItem().getItemId()); OrderItemEntity orderItemEntity = new OrderItemEntity(); orderItemEntity.setOrder(orderEntity); orderItemEntity.getPk().setLineNumber(orderItem.getLineNumber()); orderItemEntity.setItem(itemEntity); orderItemEntity.setQuantity(orderItem.getQuantity()); orderEntity.getOrderItems().add(orderItemEntity); }); OrderEntity newEntity = orderRepository.save(orderEntity); return newEntity.toOrderDto(); } } OrderService – insert vs MyBatis VS
  • 71.  JPA 설정  spring-data-jpa, hibernate-entitymanager 의존성 라이브러리 추가  EntityManagerFactoryBean, JpaTransactionManager 빈 등록  Entity 설정  @Entity, @Table, @Id, @Column, @Temporal, @GeneratedValue, @EmbeddedId, …  연관 관계 설정  @JoinColumn, @OneToMany, @ManyToOne, mappedBy, FetchType.LAZY, …  Repository interface 생성 - JpaRepository 상속  애플리케이션에서의 사용 – Entity, Repository, Pageable, … MyBatis to JPA Summary
  • 72.  상대적으로 높은 학습 곡선  But,  기술적인 진입 장벽을 낮춰줄 여러 솔루션들이 존재(e.g. Spring Data JPA, QueryDSL 등)  2015년 이후로 JPA 관련 다양한 국내 서적이 출간된 상태  JPQL에는 분명 한계가 있다  But,  Native SQL  다른 Data Access 기술과 혼용 및 분리(CQRS) 가능  그럼에도 불구하고 … JPA의 단점
  • 73. 그 동안 MyBatis로 마이 버팃으면 이제는 JPA를 한 번 써 봐야 할 때 MyBatis에서 JPA로!
  • 74. © 2018 NHN FORWARD. All rights reserved. THANK YOU
  • 75. © 2018 NHN FORWARD. All rights reserved. Q&A