SlideShare una empresa de Scribd logo
1 de 75
© 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,
update update Items set item_name = ‘’, price = 0,
select select item_id, item_name, price, category from
… …
데이터 접근 추상화와 벤더 독립성

데이터베이스 벤더마다 미묘하게 다른 데이터 타입이나 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

Más contenido relacionado

La actualidad más candente

[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio KumazawaInsight Technology, Inc.
 
Introduction To Oracle Sql
Introduction To Oracle SqlIntroduction To Oracle Sql
Introduction To Oracle SqlAhmed Yaseen
 
MySQLチューニング
MySQLチューニングMySQLチューニング
MySQLチューニングyoku0825
 
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)Yoshiro Tokumasu
 
DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門Akira Shimosako
 
Mroongaを使ったときの MySQLの制限との戦い
Mroongaを使ったときの MySQLの制限との戦いMroongaを使ったときの MySQLの制限との戦い
Mroongaを使ったときの MySQLの制限との戦いNaoya Murakami
 
MySQL Query And Index Tuning
MySQL Query And Index TuningMySQL Query And Index Tuning
MySQL Query And Index TuningManikanda kumar
 
Troubleshooting redis
Troubleshooting redisTroubleshooting redis
Troubleshooting redisDaeMyung Kang
 
Sql server エンジニアに知ってもらいたい!! sql server チューニングアプローチ
Sql server エンジニアに知ってもらいたい!! sql server チューニングアプローチSql server エンジニアに知ってもらいたい!! sql server チューニングアプローチ
Sql server エンジニアに知ってもらいたい!! sql server チューニングアプローチMasayuki Ozawa
 
Spiderストレージエンジンのご紹介
Spiderストレージエンジンのご紹介Spiderストレージエンジンのご紹介
Spiderストレージエンジンのご紹介Kentoku
 
SQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかSQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかShogo Wakayama
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Ryosuke Uchitate
 
C13 SQL Server2012知られざるTips集 by 平山理
C13 SQL Server2012知られざるTips集 by 平山理C13 SQL Server2012知られざるTips集 by 平山理
C13 SQL Server2012知られざるTips集 by 平山理Insight Technology, Inc.
 
「Oracle Database + Java + Linux」 環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1
「Oracle Database + Java + Linux」環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1「Oracle Database + Java + Linux」環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1
「Oracle Database + Java + Linux」 環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1Shogo Wakayama
 
Mysql index
Mysql indexMysql index
Mysql indexYuan Yao
 
SQL Server パフォーマンス問題対処 Deep Dive
SQL Server パフォーマンス問題対処 Deep DiveSQL Server パフォーマンス問題対処 Deep Dive
SQL Server パフォーマンス問題対処 Deep DiveKoichiro Sasaki
 

La actualidad más candente (20)

[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
[B31,32]SQL Server Internal と パフォーマンスチューニング by Yukio Kumazawa
 
Introduction To Oracle Sql
Introduction To Oracle SqlIntroduction To Oracle Sql
Introduction To Oracle Sql
 
MySQLチューニング
MySQLチューニングMySQLチューニング
MySQLチューニング
 
Index in sql server
Index in sql serverIndex in sql server
Index in sql server
 
SQL Server 入門
SQL Server 入門SQL Server 入門
SQL Server 入門
 
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
 
DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門DBパフォーマンスチューニングの基礎:インデックス入門
DBパフォーマンスチューニングの基礎:インデックス入門
 
Mroongaを使ったときの MySQLの制限との戦い
Mroongaを使ったときの MySQLの制限との戦いMroongaを使ったときの MySQLの制限との戦い
Mroongaを使ったときの MySQLの制限との戦い
 
Pro Postgres 9
Pro Postgres 9Pro Postgres 9
Pro Postgres 9
 
Indexes in postgres
Indexes in postgresIndexes in postgres
Indexes in postgres
 
MySQL Query And Index Tuning
MySQL Query And Index TuningMySQL Query And Index Tuning
MySQL Query And Index Tuning
 
Troubleshooting redis
Troubleshooting redisTroubleshooting redis
Troubleshooting redis
 
Sql server エンジニアに知ってもらいたい!! sql server チューニングアプローチ
Sql server エンジニアに知ってもらいたい!! sql server チューニングアプローチSql server エンジニアに知ってもらいたい!! sql server チューニングアプローチ
Sql server エンジニアに知ってもらいたい!! sql server チューニングアプローチ
 
Spiderストレージエンジンのご紹介
Spiderストレージエンジンのご紹介Spiderストレージエンジンのご紹介
Spiderストレージエンジンのご紹介
 
SQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するかSQL大量発行処理をいかにして高速化するか
SQL大量発行処理をいかにして高速化するか
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
 
C13 SQL Server2012知られざるTips集 by 平山理
C13 SQL Server2012知られざるTips集 by 平山理C13 SQL Server2012知られざるTips集 by 平山理
C13 SQL Server2012知られざるTips集 by 平山理
 
「Oracle Database + Java + Linux」 環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1
「Oracle Database + Java + Linux」環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1「Oracle Database + Java + Linux」環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1
「Oracle Database + Java + Linux」 環境における性能問題の調査手法 ~ミッションクリティカルシステムの現場から~ Part.1
 
Mysql index
Mysql indexMysql index
Mysql index
 
SQL Server パフォーマンス問題対処 Deep Dive
SQL Server パフォーマンス問題対処 Deep DiveSQL Server パフォーマンス問題対処 Deep Dive
SQL Server パフォーマンス問題対処 Deep Dive
 

Similar a MyBatis에서 JPA로

[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로NHN FORWARD
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3plusperson
 
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
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술NAVER D2
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Hyosang Hong
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
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
 
Ksug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaKsug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaYounghan Kim
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기경원 이
 
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?JaewonLee153
 
영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA경원 이
 

Similar a MyBatis에서 JPA로 (20)

[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] 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
 
Jlook open api platform-appdevguide
Jlook open api platform-appdevguideJlook open api platform-appdevguide
Jlook open api platform-appdevguide
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료Jpa 쿼리 포함 자료
Jpa 쿼리 포함 자료
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Swt J Face 2/3
Swt J Face 2/3Swt J Face 2/3
Swt J Face 2/3
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3
 
Hibernate 기초
Hibernate 기초Hibernate 기초
Hibernate 기초
 
Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리
 
Ksug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaKsug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpa
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
Srping data rest
Srping data restSrping data rest
Srping data rest
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
(Spring Data JPA)식별자(@Id, Primary Key) 자동 생성, @GeneratedValue의 strategy 속성,Ge...
(Spring Data JPA)식별자(@Id, Primary Key) 자동 생성, @GeneratedValue의 strategy 속성,Ge...(Spring Data JPA)식별자(@Id, Primary Key) 자동 생성, @GeneratedValue의 strategy 속성,Ge...
(Spring Data JPA)식별자(@Id, Primary Key) 자동 생성, @GeneratedValue의 strategy 속성,Ge...
 
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
 
영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA영속성 컨텍스트로 보는 JPA
영속성 컨텍스트로 보는 JPA
 

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, update update Items set item_name = ‘’, price = 0, select select item_id, item_name, price, category from … …
  • 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을 이용해서 관계 테이블을 참조  객체는 참조를 사용해서 연관된 객체를 참조 연관 관계 설정
  • 47. 연관 관계 설정 public class OrderItemEntity { // ... @ManyToOne @JoinColumn(name = "item_id") private ItemEntity item; } 예) 연관 관계 설정 OrderItemEntity – ItemEntity 연관 관계 설정
  • 48. 방향성  단방향(unidirectional)  양방향(bidirectional) 양방향 연관 관계  관계의 주인(owner)  연관 관계의 주인은 외래 키(FK)가 있는 곳  연관 관계의 주인이 아닌 경우, mappedBy 속성으로 연관 관계의 주인을 지정 연관 관계 설정
  • 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