SlideShare ist ein Scribd-Unternehmen logo
1 von 31
Spring Boot with MyBatis
KESTI 개발팀
Spring Boot with MyBatis
• mybatis-spring-boot-starter 소개
• MyBatis Tutorials
• setup
• mappers
• testing
• Bonus Tutorials
• Flyway
• QueryDSL
2016-10-12KESTI 개발팀 세미나 2
MyBatis for Spring Boot
• MyBatis 를 Spring Boot Application 에서 사용하기 위한
라이브러리
• 홈페이지 : http://www.mybatis.org/mybatis-spring-boot/
• 소스 : https://github.com/mybatis/mybatis-spring-boot
• 예제 :
• KESTI SpringBoot-MyBatis Tutorials
• Spring Boot 에서 Java Config를 통해 myBatis 연동하기
2016-10-12KESTI 개발팀 세미나 3
MyBatis Tutorials
2016-10-12KESTI 개발팀 세미나 4
Tutorial Overview
1. mybatis-spring-boot-starter 프로젝트 구성
2. Mapper – Annotation / XML 방식
3. MyBatis 설정 방법
4. Flyway 를 이용한 database migration 방법
5. MyBatis 단위 테스트
2016-10-12KESTI 개발팀 세미나 5
1. 프로젝트 구성
<dependencies>
<dependency>
<groupId>kr.kesti.kesti4j</groupId>
<artifactId>kesti4j-data-java6</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
2016-10-12KESTI 개발팀 세미나 6
Project Structures
configuration
data handling source
Spring Boot Application
Flyway database migration
MyBatis configuration & XML Mappers
환경설정 정보
Test 코드
2016-10-12KESTI 개발팀 세미나 7
XML Mapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.kesti.mybatis.examples.domain.models">
<select id="selectActorByFirstname" parameterType="String" resultType="Actor">
SELECT * FROM Actors WHERE firstname = #{firstname} limit 1
</select>
<insert id="insertActor" useGeneratedKeys="true" keyProperty="id">
insert into Actors(firstname, lastname)
values( #{firstname}, #{lastname} )
</insert>
<!-- Oracle, PostgreSQL 은 SEQUENCE -->
<!--
<insert id="insertActorBySequence">
<selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED">
SELECT SEQ_ID.nextval FROM DUAL
</selectKey>
INSERT INTO Autors (id, firstname, lastname)
VALUES (#{id}, #{firstname}, #{lastname})
</insert>
-->
</mapper>
2016-10-12KESTI 개발팀 세미나 8
Annotated Mapper
/**
* Actor 를 위한 MyBatis Mapper 입니다.
*/
public interface ActorMapper {
@Select("SELECT * FROM Actors WHERE firstname = #{firstname}")
Actor findByFirstname(@Param("firstname") String firstname);
@Select("SELECT * FROM Actors")
List<Actor> findAll();
@Delete("DELETE FROM Actors WHERE id=#{id}")
void deleteById(@Param("id") Integer id);
}
/**
* MyBatis 를 Spring boot 에서 사용하기 위한 환경설정
*/
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackageClasses = { ActorRepository.class })
@MapperScan(basePackageClasses = { ActorMapper.class })
public class MyBatisConfiguration extends AbstractFlywayMyBatisConfiguration {
2016-10-12KESTI 개발팀 세미나 9
XML Mapper
보다 좋은점은?
Repository / DAO
/**
* {@link Actor} 를 위한 Repository (DAO) 입니다.
*/
@Slf4j
@Repository
public class ActorRepository {
@Autowired ActorMapper mapper;
@Autowired SqlSessionTemplate session;
public Actor findByFirstname(@NonNull String firstname) {
return mapper.findByFirstname(firstname);
}
public Actor findByFirstnameWithXmlMapper(@NonNull String firstname) {
return session.selectOne("selectActorByFirstname", firstname);
}
public List<Actor> findAll() {
return mapper.findAll();
}
public int insertActor(@NonNull Actor actor) {
return session.insert("insertActor", actor);
}
public void deleteById(@NonNull Integer id) {
mapper.deleteById(id);
}
}
2016-10-12KESTI 개발팀 세미나 10
MyBatis JavaConfig
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackageClasses = { ActorRepository.class })
@MapperScan(basePackageClasses = { ActorMapper.class })
public class MyBatisConfiguration extends AbstractFlywayMyBatisConfiguration {
// datasource 용 properties (application.properties 에서 자동으로 정보를 읽어옴)
@Inject DataSourceProperties dataSourceProperties;
// mybatis 용 properties (application.properties 에서 자동으로 정보를 읽어옴)
@Inject MybatisProperties mybatisProperties;
@Override
protected DatabaseSetting getDatabaseSetting() {
return DatabaseSetting.builder()
.driverClass(dataSourceProperties.getDriverClassName())
.jdbcUrl(dataSourceProperties.getUrl())
.build();
}
@Override
protected String getMyBatisConfigPath() {
return mybatisProperties.getConfig();
}
@Override
protected String getMyBatisMapperPath() {
return mybatisProperties.getMapperLocations()[0];
}
}
2016-10-12KESTI 개발팀 세미나 11
XML Config
와 장단점
비교
Spring Boot application.properties
### DataSource
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.jdbc-url=jdbc:h2:mem
spring.datasource.username=sa
spring.datasource.password=
### MyBatis
mybatis.config=mybatis/mybatis-config.xml
mybatis.mapper-locations=mybatis/mappers/**/*Mapper.xml
mybatis.executor-type=simple
### Logging
logging.level.root=info
logging.level.kr.kesti.mybatis.examples=debug
2016-10-12KESTI 개발팀 세미나 12
Database Setup by Flyway
/**
* Flyway 를 이용한 DB Migration 을 수행하도록 합니다.
*
* @param dataSource DataSource
* @return {@link Flyway} 인스턴스
*/
@Bean(initMethod = "migrate")
protected Flyway flyway(DataSource dataSource) {
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
if (cleanDatabaseForTest()) {
flyway.clean();
}
return flyway;
}
CREATE TABLE Actors (
id SERIAL PRIMARY KEY,
firstname VARCHAR(64),
lastname VARCHAR(64)
);
INSERT INTO Actors (firstname, lastname) VALUES
('Sunghyouk', 'Bae');
INSERT INTO Actors (firstname, lastname) VALUES ('Misook',
'Kwon');
INSERT INTO Actors (firstname, lastname) VALUES ('Jehyoung',
'Bae');
INSERT INTO Actors (firstname, lastname) VALUES ('Jinseok',
'Kwon');
INSERT INTO Actors (firstname, lastname) VALUES ('Kildong',
'Hong');
2016-10-12KESTI 개발팀 세미나 13
Configuration Test
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { MyBatisConfiguration.class })
public class MyBatisConfigurationTest {
@Inject ActorMapper actorMapper;
@Inject ActorRepository actorRepository;
@Inject private SqlSessionFactory sf;
@Test
public void testConfiguration() {
assertThat(actorMapper).isNotNull();
assertThat(actorRepository).isNotNull();
assertThat(sf).isNotNull();
}
}
2016-10-12KESTI 개발팀 세미나 14
Repository Test
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { MyBatisConfiguration.class })
public class ActorRepositoryTest {
@Inject ActorRepository actorRepo;
private static final String FIRST_NAME = "Sunghyouk";
@Test
public void testConfiguration() {
assertThat(actorRepo).isNotNull();
}
@Test
public void testFindByFirstname() {
Actor actor = actorRepo.findByFirstname(FIRST_NAME);
assertThat(actor).isNotNull();
}
@Test
public void testFindByFirstnameWithXmlMapper() {
Actor actor = actorRepo.findByFirstnameWithXmlMapper(FIRST_NAME);
assertThat(actor).isNotNull();
}
@Test
public void testFindAll() {
List<Actor> actors = actorRepo.findAll();
assertThat(actors.size()).isGreaterThan(0);
}
@Test
public void testInsertActor() {
String firstname = "mybatis";
Actor actor = Actor.of(null, firstname, "kesti");
int rowCount = actorRepo.insertActor(actor);
log.debug("rowCount={}", rowCount);
actor = actorRepo.findByFirstname(firstname);
log.debug("actor={}", actor);
assertThat(actor).isNotNull();
assertThat(actor.getFirstname()).isEqualTo(firstname);
actorRepo.deleteById(actor.getId());
}
}
2016-10-12KESTI 개발팀 세미나 15
Flyway
Evolve your Database Schema easily and
reliably across all your instances
2016-10-12KESTI 개발팀 세미나 16
Code 관리는 git
2016-10-12KESTI 개발팀 세미나 17
DB 형상 관리는?
DB Schema Control by Dev Step
2016-10-12KESTI 개발팀 세미나 18
DB Schema Version Control
2016-10-12KESTI 개발팀 세미나 19
QueryDSL
Unified Queries for Java with Typesafe
2016-10-12KESTI 개발팀 세미나 20
QueryDSL 개요
• 질의어를 문자열이 아닌 Java Code로 표현
• Query문 – type check 불가 / 실행 전에는 오류 검출 불가
• Java Code는
• Compile Error를 미리 검출
• Code assistant 활용 100%
• Refactoring 용이
• 다양한 저장소에 대한 일관된 질의어 제작 가능
• Collection, RDBMS, MongoDB, Lucene …
• .NET 의 LINQ 같은 목적 (Langunage-INtegrated Query)
• 참고 : 한글 매뉴얼 (단 3.4.0 기준임. 4.x 는 package 명이
달라졌음)
2016-10-12KESTI 개발팀 세미나 21
QueryDSL 적용 범위
JPA (Java Persistence API)
JDO (Java Data Object)
SQL
Lucence
MongoDB
Collections
QueryDSL
RDBMS
ORM
Lucene
(search
engine)
MongoD
B
List / Map
2016-10-12KESTI 개발팀 세미나 22
QueryDSL for SQL
• Select
• Join (innerJoin, join, leftJoin, rightJoin, fullJoin)
• group by / having
• order by
• limit / offset / restrict
• subquery
• Window functions
• Common Table Expression (CTE)
• Insert
• Update
• Delete
2016-10-12KESTI 개발팀 세미나 23
SELECT with Projections
2016-10-12KESTI 개발팀 세미나 24
QActors $ = QActors.actors;
List<Tuple> rows = query.select($.id, $.firstname, $.lastname)
.from($)
.fetch();
QActors $ = QActors.actors;
List<Actor> actors = query.select(Projections.constructor(Actor.class,
$.id,
$.firstname,
$.lastname))
.from($)
.fetch();
SELECT – Filter, GroupBy
2016-10-12KESTI 개발팀 세미나 25
Actor actor = query.select(Projections.constructor(Actor.class,
$.id,
$.firstname,
$.lastname))
.from($)
.where($.lastname.eq("Bae"))
.fetchFirst();
List<Tuple> rows = query.select($.lastname, $.lastname.count().as("cnt"))
.from($)
.groupBy($.lastname)
.fetch();
SELECT : Subquery
2016-10-12KESTI 개발팀 세미나 26
QActors $ = QActors.actors;
QActors $2 = new QActors("$2");
SQLQuery<Actor> sq = query.select(Projections.constructor(Actor.class,
$.id,
$.firstname,
$.lastname))
.from($)
.where($.id.eq(SQLExpressions.select($2.id.max()).from($2)));
List<Actor> actors = sq.fetch();
CUD
2016-10-12KESTI 개발팀 세미나 27
QActors $ = QActors.actors;
long inserted = query.insert($)
.columns($.firstname, $.lastname)
.values("querydsl", "examples")
.execute();
long updated = query.update($)
.set($.lastname, "updated examples")
.where($.firstname.eq("querydsl"))
.execute();
long deleted = query.delete($)
.where($.firstname.eq("querydsl"))
.execute();
CUD Batch Execution
2016-10-12KESTI 개발팀 세미나 28
QActors $ = QActors.actors;
int COUNT = 100;
// INSERT
SQLInsertClause insertClause = query.insert($);
for (int i = 0; i < COUNT; i++) {
insertClause.set($.firstname, "firstname-" + i)
.set($.lastname, "lastname-" + i)
.addBatch();
}
long insertedCount = insertClause.execute();
// UPDATE
SQLUpdateClause updateClause = query.update($);
for (int i = 0; i < COUNT; i++) {
updateClause.set($.firstname, "updated-firstname-" + i)
.where($.lastname.eq("lastname-" + i))
.addBatch();
}
long updatedCount = updateClause.execute();
// DELETE
SQLDeleteClause deleteClause = query.delete($);
for (int i = 0; i < COUNT; i++) {
deleteClause.where($.firstname.eq("updated-firstname-" + i))
.addBatch();
}
long deletedCount = deleteClause.execute();
QueryDSL Dependency
2016-10-12KESTI 개발팀 세미나 29
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql</artifactId>
<version>${com.querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spring</artifactId>
<version>${com.querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-codegen</artifactId>
<version>${com.querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-spatial</artifactId>
<version>${com.querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-sql-spatial</artifactId>
<version>${com.querydsl.version}</version>
</dependency>
QueryDSL APT
2016-10-12KESTI 개발팀 세미나 30
<plugin>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>${com.querydsl.version}</version>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbcDriver>org.postgresql.Driver</jdbcDriver>
<jdbcUrl>jdbc:postgresql://localhost/querydsl</jdbcUrl>
<jdbcUser>root</jdbcUser>
<jdbcPassword>root</jdbcPassword>
<packageName>kesti4j.data.querydsl.models</packageName>
<sourceFolder>${project.basedir}/target/generated-sources/java</sourceFolder>
<targetFolder>${project.basedir}/target/generated-sources/java</targetFolder>
<spatial>true</spatial>
</configuration>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1206-jdbc42</version>
</dependency>
</dependencies>
</plugin>
QueryDSL Generated Code
2016-10-12KESTI 개발팀 세미나 31
/**
* QActors is a Querydsl query type for QActors
*/
@Generated("com.querydsl.sql.codegen.MetaDataSerializer")
public class QActors extends RelationalPathSpatial<QActors> {
private static final long serialVersionUID = 822224394;
public static final QActors actors = new QActors("actors");
public final StringPath firstname = createString("firstname");
public final NumberPath<Integer> id = createNumber("id", Integer.class);
public final StringPath lastname = createString("lastname");
public final com.querydsl.sql.PrimaryKey<QActors> actorsPkey = createPrimaryKey(id);
public QActors(String variable) {
super(QActors.class, forVariable(variable), "public", "actors");
addMetadata();
}
public QActors(String variable, String schema, String table) {
super(QActors.class, forVariable(variable), schema, table);
addMetadata();
}
public QActors(Path<? extends QActors> path) {
super(path.getType(), path.getMetadata(), "public", "actors");
addMetadata();
}
public QActors(PathMetadata metadata) {
super(QActors.class, metadata, "public", "actors");
addMetadata();
}
public void addMetadata() {
addMetadata(firstname, ColumnMetadata.named("firstname").withIndex(2).ofType(Types.VARCHAR).withSize(64));
addMetadata(id, ColumnMetadata.named("id").withIndex(1).ofType(Types.INTEGER).withSize(10).notNull());
addMetadata(lastname, ColumnMetadata.named("lastname").withIndex(3).ofType(Types.VARCHAR).withSize(64));
}
}

Weitere ähnliche Inhalte

Was ist angesagt?

Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API07.pallav
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring bootAntoine Rey
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOPDzmitry Naskou
 
Kafka connect 101
Kafka connect 101Kafka connect 101
Kafka connect 101Whiteklay
 
Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introductionRasheed Waraich
 
Event Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
Event Driven Systems with Spring Boot, Spring Cloud Streams and KafkaEvent Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
Event Driven Systems with Spring Boot, Spring Cloud Streams and KafkaVMware Tanzu
 
Introduction to Spring Boot!
Introduction to Spring Boot!Introduction to Spring Boot!
Introduction to Spring Boot!Jakub Kubrynski
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVCDzmitry Naskou
 
내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015Lim SungHyun
 
Understanding REST APIs in 5 Simple Steps
Understanding REST APIs in 5 Simple StepsUnderstanding REST APIs in 5 Simple Steps
Understanding REST APIs in 5 Simple StepsTessa Mero
 
Microservices with Java, Spring Boot and Spring Cloud
Microservices with Java, Spring Boot and Spring CloudMicroservices with Java, Spring Boot and Spring Cloud
Microservices with Java, Spring Boot and Spring CloudEberhard Wolff
 
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20Phil Wilkins
 

Was ist angesagt? (20)

Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
 
Spring annotation
Spring annotationSpring annotation
Spring annotation
 
Kafka connect 101
Kafka connect 101Kafka connect 101
Kafka connect 101
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring boot introduction
Spring boot introductionSpring boot introduction
Spring boot introduction
 
Event Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
Event Driven Systems with Spring Boot, Spring Cloud Streams and KafkaEvent Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
Event Driven Systems with Spring Boot, Spring Cloud Streams and Kafka
 
Spring boot
Spring bootSpring boot
Spring boot
 
Express js
Express jsExpress js
Express js
 
PHP filter
PHP filterPHP filter
PHP filter
 
Introduction to Spring Boot!
Introduction to Spring Boot!Introduction to Spring Boot!
Introduction to Spring Boot!
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
 
Xke spring boot
Xke spring bootXke spring boot
Xke spring boot
 
내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015
 
Understanding REST APIs in 5 Simple Steps
Understanding REST APIs in 5 Simple StepsUnderstanding REST APIs in 5 Simple Steps
Understanding REST APIs in 5 Simple Steps
 
Microservices with Java, Spring Boot and Spring Cloud
Microservices with Java, Spring Boot and Spring CloudMicroservices with Java, Spring Boot and Spring Cloud
Microservices with Java, Spring Boot and Spring Cloud
 
Flask Basics
Flask BasicsFlask Basics
Flask Basics
 
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
 

Andere mochten auch

MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제정완 전
 
Springboot and camel
Springboot and camelSpringboot and camel
Springboot and camelDeepak Kumar
 
SeaJUG May 2012 mybatis
SeaJUG May 2012 mybatisSeaJUG May 2012 mybatis
SeaJUG May 2012 mybatisWill Iverson
 
How to Choose an API Automation Tool for a Distributed Cloud-based App: To...
How to Choose an API Automation Tool for a Distributed Cloud-based App: To...How to Choose an API Automation Tool for a Distributed Cloud-based App: To...
How to Choose an API Automation Tool for a Distributed Cloud-based App: To...Altoros
 
Secure RESTful API Automation With JavaScript
Secure RESTful API Automation With JavaScriptSecure RESTful API Automation With JavaScript
Secure RESTful API Automation With JavaScriptJonathan LeBlanc
 
OpenERP 6.1 Framework Changes
OpenERP 6.1 Framework ChangesOpenERP 6.1 Framework Changes
OpenERP 6.1 Framework ChangesOdoo
 
Design Summit - RESTful API Overview - John Hardy
Design Summit - RESTful API Overview - John HardyDesign Summit - RESTful API Overview - John Hardy
Design Summit - RESTful API Overview - John HardyManageIQ
 
Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...
Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...
Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...Vladimir Bacvanski, PhD
 
좌충우돌 ORM 개발기 | Devon 2012
좌충우돌 ORM 개발기 | Devon 2012좌충우돌 ORM 개발기 | Devon 2012
좌충우돌 ORM 개발기 | Devon 2012Daum DNA
 
Светлана Исакова «Язык Kotlin»
Светлана Исакова «Язык Kotlin»Светлана Исакова «Язык Kotlin»
Светлана Исакова «Язык Kotlin»e-Legion
 
RESTful API Automation with JavaScript
RESTful API Automation with JavaScriptRESTful API Automation with JavaScript
RESTful API Automation with JavaScriptJonathan LeBlanc
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in actionCiro Rizzo
 
A brief introduction to Realm with Kotlin
A brief introduction to Realm with KotlinA brief introduction to Realm with Kotlin
A brief introduction to Realm with KotlinLeonardo YongUk Kim
 
Frisby: Rest API Automation Framework
Frisby: Rest API Automation FrameworkFrisby: Rest API Automation Framework
Frisby: Rest API Automation FrameworkQuovantis
 
Agile 2014 - Personal Kanban
Agile 2014 - Personal KanbanAgile 2014 - Personal Kanban
Agile 2014 - Personal KanbanDerek Huether
 
Web API Test Automation using Frisby & Node.js
Web API Test Automation using Frisby  & Node.jsWeb API Test Automation using Frisby  & Node.js
Web API Test Automation using Frisby & Node.jsChi Lang Le Vu Tran
 

Andere mochten auch (20)

MyBatis
MyBatisMyBatis
MyBatis
 
Springboot Overview
Springboot  OverviewSpringboot  Overview
Springboot Overview
 
MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제
 
Springboot and camel
Springboot and camelSpringboot and camel
Springboot and camel
 
SeaJUG May 2012 mybatis
SeaJUG May 2012 mybatisSeaJUG May 2012 mybatis
SeaJUG May 2012 mybatis
 
How to Choose an API Automation Tool for a Distributed Cloud-based App: To...
How to Choose an API Automation Tool for a Distributed Cloud-based App: To...How to Choose an API Automation Tool for a Distributed Cloud-based App: To...
How to Choose an API Automation Tool for a Distributed Cloud-based App: To...
 
Secure RESTful API Automation With JavaScript
Secure RESTful API Automation With JavaScriptSecure RESTful API Automation With JavaScript
Secure RESTful API Automation With JavaScript
 
OpenERP 6.1 Framework Changes
OpenERP 6.1 Framework ChangesOpenERP 6.1 Framework Changes
OpenERP 6.1 Framework Changes
 
Design Summit - RESTful API Overview - John Hardy
Design Summit - RESTful API Overview - John HardyDesign Summit - RESTful API Overview - John Hardy
Design Summit - RESTful API Overview - John Hardy
 
Telephonic etiquettes
Telephonic  etiquettesTelephonic  etiquettes
Telephonic etiquettes
 
Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...
Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...
Crash Introduction to Modern Java Data Access: Understanding JPA, Hibernate, ...
 
좌충우돌 ORM 개발기 | Devon 2012
좌충우돌 ORM 개발기 | Devon 2012좌충우돌 ORM 개발기 | Devon 2012
좌충우돌 ORM 개발기 | Devon 2012
 
Светлана Исакова «Язык Kotlin»
Светлана Исакова «Язык Kotlin»Светлана Исакова «Язык Kotlin»
Светлана Исакова «Язык Kotlin»
 
RESTful API Automation with JavaScript
RESTful API Automation with JavaScriptRESTful API Automation with JavaScript
RESTful API Automation with JavaScript
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in action
 
Querydsl overview 2014
Querydsl overview 2014Querydsl overview 2014
Querydsl overview 2014
 
A brief introduction to Realm with Kotlin
A brief introduction to Realm with KotlinA brief introduction to Realm with Kotlin
A brief introduction to Realm with Kotlin
 
Frisby: Rest API Automation Framework
Frisby: Rest API Automation FrameworkFrisby: Rest API Automation Framework
Frisby: Rest API Automation Framework
 
Agile 2014 - Personal Kanban
Agile 2014 - Personal KanbanAgile 2014 - Personal Kanban
Agile 2014 - Personal Kanban
 
Web API Test Automation using Frisby & Node.js
Web API Test Automation using Frisby  & Node.jsWeb API Test Automation using Frisby  & Node.js
Web API Test Automation using Frisby & Node.js
 

Ähnlich wie SpringBoot with MyBatis, Flyway, QueryDSL

OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...mfrancis
 
OSGi and Spring Data for simple (Web) Application Development
OSGi and Spring Data  for simple (Web) Application DevelopmentOSGi and Spring Data  for simple (Web) Application Development
OSGi and Spring Data for simple (Web) Application DevelopmentChristian Baranowski
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Webpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usWebpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usStefan Adolf
 
Quick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerQuick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerNic Raboy
 
Kharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backendKharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backendMax Klymyshyn
 
Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)Gunith Devasurendra
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyMark Proctor
 
Spring design-juergen-qcon
Spring design-juergen-qconSpring design-juergen-qcon
Spring design-juergen-qconYiwei Ma
 
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdfdokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdfAppster1
 
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdfdokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdfAppster1
 
Spring5 New Features
Spring5 New FeaturesSpring5 New Features
Spring5 New FeaturesJay Lee
 
Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4Yuriy Shapovalov
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
 
Grails, Trails, and Sails: Rails Through a Coffee Filter
Grails, Trails, and Sails: Rails Through a Coffee FilterGrails, Trails, and Sails: Rails Through a Coffee Filter
Grails, Trails, and Sails: Rails Through a Coffee Filterelliando dias
 
Come abbiamo scalato Dazn con micro-architetture
Come abbiamo scalato Dazn con micro-architettureCome abbiamo scalato Dazn con micro-architetture
Come abbiamo scalato Dazn con micro-architettureCommit University
 
jclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian Colejclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian ColeEverett Toews
 
Back to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDBBack to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDBMongoDB
 

Ähnlich wie SpringBoot with MyBatis, Flyway, QueryDSL (20)

OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
OSGi and Spring Data for simple (Web) Application Development - Christian Bar...
 
OSGi and Spring Data for simple (Web) Application Development
OSGi and Spring Data  for simple (Web) Application DevelopmentOSGi and Spring Data  for simple (Web) Application Development
OSGi and Spring Data for simple (Web) Application Development
 
Introducing jee7 – jsf 2
Introducing jee7 – jsf 2Introducing jee7 – jsf 2
Introducing jee7 – jsf 2
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Webpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of usWebpack Encore - Asset Management for the rest of us
Webpack Encore - Asset Management for the rest of us
 
Quick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase ServerQuick and Easy Development with Node.js and Couchbase Server
Quick and Easy Development with Node.js and Couchbase Server
 
Kharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backendKharkivpy#3: Javascript and Python backend
Kharkivpy#3: Javascript and Python backend
 
Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
 
Spring design-juergen-qcon
Spring design-juergen-qconSpring design-juergen-qcon
Spring design-juergen-qcon
 
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdfdokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
 
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdfdokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
 
Spring5 New Features
Spring5 New FeaturesSpring5 New Features
Spring5 New Features
 
Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4Single Page Applications on JavaScript and ASP.NET MVC4
Single Page Applications on JavaScript and ASP.NET MVC4
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
 
Grails, Trails, and Sails: Rails Through a Coffee Filter
Grails, Trails, and Sails: Rails Through a Coffee FilterGrails, Trails, and Sails: Rails Through a Coffee Filter
Grails, Trails, and Sails: Rails Through a Coffee Filter
 
Come abbiamo scalato Dazn con micro-architetture
Come abbiamo scalato Dazn con micro-architettureCome abbiamo scalato Dazn con micro-architetture
Come abbiamo scalato Dazn con micro-architetture
 
Liferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for DevelopersLiferay (DXP) 7 Tech Meetup for Developers
Liferay (DXP) 7 Tech Meetup for Developers
 
jclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian Colejclouds High Level Overview by Adrian Cole
jclouds High Level Overview by Adrian Cole
 
Back to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDBBack to Basics, webinar 2: La tua prima applicazione MongoDB
Back to Basics, webinar 2: La tua prima applicazione MongoDB
 

Mehr von Sunghyouk Bae

JUnit5 and TestContainers
JUnit5 and TestContainersJUnit5 and TestContainers
JUnit5 and TestContainersSunghyouk Bae
 
Introduction of failsafe
Introduction of failsafeIntroduction of failsafe
Introduction of failsafeSunghyouk Bae
 
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Sunghyouk Bae
 
Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Sunghyouk Bae
 
Alternatives of JPA/Hibernate
Alternatives of JPA/HibernateAlternatives of JPA/Hibernate
Alternatives of JPA/HibernateSunghyouk Bae
 
Kotlin coroutines and spring framework
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring frameworkSunghyouk Bae
 
Java naming strategy (자바 명명 전략)
Java naming strategy (자바 명명 전략)Java naming strategy (자바 명명 전략)
Java naming strategy (자바 명명 전략)Sunghyouk Bae
 
테스트자동화와 TDD
테스트자동화와 TDD테스트자동화와 TDD
테스트자동화와 TDDSunghyouk Bae
 
좋은 개발자 되기
좋은 개발자 되기좋은 개발자 되기
좋은 개발자 되기Sunghyouk Bae
 
Multithread pattern 소개
Multithread pattern 소개Multithread pattern 소개
Multithread pattern 소개Sunghyouk Bae
 

Mehr von Sunghyouk Bae (16)

JUnit5 and TestContainers
JUnit5 and TestContainersJUnit5 and TestContainers
JUnit5 and TestContainers
 
Introduction of failsafe
Introduction of failsafeIntroduction of failsafe
Introduction of failsafe
 
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
 
Spring data requery
Spring data requerySpring data requery
Spring data requery
 
Requery overview
Requery overviewRequery overview
Requery overview
 
Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017
 
measure metrics
measure metricsmeasure metrics
measure metrics
 
Alternatives of JPA/Hibernate
Alternatives of JPA/HibernateAlternatives of JPA/Hibernate
Alternatives of JPA/Hibernate
 
Kotlin coroutines and spring framework
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring framework
 
Java naming strategy (자바 명명 전략)
Java naming strategy (자바 명명 전략)Java naming strategy (자바 명명 전략)
Java naming strategy (자바 명명 전략)
 
테스트자동화와 TDD
테스트자동화와 TDD테스트자동화와 TDD
테스트자동화와 TDD
 
JUnit & AssertJ
JUnit & AssertJJUnit & AssertJ
JUnit & AssertJ
 
좋은 개발자 되기
좋은 개발자 되기좋은 개발자 되기
좋은 개발자 되기
 
Using AdoRepository
Using AdoRepositoryUsing AdoRepository
Using AdoRepository
 
Multithread pattern 소개
Multithread pattern 소개Multithread pattern 소개
Multithread pattern 소개
 
Strategy Maps
Strategy MapsStrategy Maps
Strategy Maps
 

Kürzlich hochgeladen

BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedDelhi Call girls
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ
 

Kürzlich hochgeladen (20)

BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide Deck
 

SpringBoot with MyBatis, Flyway, QueryDSL

  • 1. Spring Boot with MyBatis KESTI 개발팀
  • 2. Spring Boot with MyBatis • mybatis-spring-boot-starter 소개 • MyBatis Tutorials • setup • mappers • testing • Bonus Tutorials • Flyway • QueryDSL 2016-10-12KESTI 개발팀 세미나 2
  • 3. MyBatis for Spring Boot • MyBatis 를 Spring Boot Application 에서 사용하기 위한 라이브러리 • 홈페이지 : http://www.mybatis.org/mybatis-spring-boot/ • 소스 : https://github.com/mybatis/mybatis-spring-boot • 예제 : • KESTI SpringBoot-MyBatis Tutorials • Spring Boot 에서 Java Config를 통해 myBatis 연동하기 2016-10-12KESTI 개발팀 세미나 3
  • 5. Tutorial Overview 1. mybatis-spring-boot-starter 프로젝트 구성 2. Mapper – Annotation / XML 방식 3. MyBatis 설정 방법 4. Flyway 를 이용한 database migration 방법 5. MyBatis 단위 테스트 2016-10-12KESTI 개발팀 세미나 5
  • 7. Project Structures configuration data handling source Spring Boot Application Flyway database migration MyBatis configuration & XML Mappers 환경설정 정보 Test 코드 2016-10-12KESTI 개발팀 세미나 7
  • 8. XML Mapper <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="kr.kesti.mybatis.examples.domain.models"> <select id="selectActorByFirstname" parameterType="String" resultType="Actor"> SELECT * FROM Actors WHERE firstname = #{firstname} limit 1 </select> <insert id="insertActor" useGeneratedKeys="true" keyProperty="id"> insert into Actors(firstname, lastname) values( #{firstname}, #{lastname} ) </insert> <!-- Oracle, PostgreSQL 은 SEQUENCE --> <!-- <insert id="insertActorBySequence"> <selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED"> SELECT SEQ_ID.nextval FROM DUAL </selectKey> INSERT INTO Autors (id, firstname, lastname) VALUES (#{id}, #{firstname}, #{lastname}) </insert> --> </mapper> 2016-10-12KESTI 개발팀 세미나 8
  • 9. Annotated Mapper /** * Actor 를 위한 MyBatis Mapper 입니다. */ public interface ActorMapper { @Select("SELECT * FROM Actors WHERE firstname = #{firstname}") Actor findByFirstname(@Param("firstname") String firstname); @Select("SELECT * FROM Actors") List<Actor> findAll(); @Delete("DELETE FROM Actors WHERE id=#{id}") void deleteById(@Param("id") Integer id); } /** * MyBatis 를 Spring boot 에서 사용하기 위한 환경설정 */ @Configuration @EnableAutoConfiguration @ComponentScan(basePackageClasses = { ActorRepository.class }) @MapperScan(basePackageClasses = { ActorMapper.class }) public class MyBatisConfiguration extends AbstractFlywayMyBatisConfiguration { 2016-10-12KESTI 개발팀 세미나 9 XML Mapper 보다 좋은점은?
  • 10. Repository / DAO /** * {@link Actor} 를 위한 Repository (DAO) 입니다. */ @Slf4j @Repository public class ActorRepository { @Autowired ActorMapper mapper; @Autowired SqlSessionTemplate session; public Actor findByFirstname(@NonNull String firstname) { return mapper.findByFirstname(firstname); } public Actor findByFirstnameWithXmlMapper(@NonNull String firstname) { return session.selectOne("selectActorByFirstname", firstname); } public List<Actor> findAll() { return mapper.findAll(); } public int insertActor(@NonNull Actor actor) { return session.insert("insertActor", actor); } public void deleteById(@NonNull Integer id) { mapper.deleteById(id); } } 2016-10-12KESTI 개발팀 세미나 10
  • 11. MyBatis JavaConfig @Configuration @EnableAutoConfiguration @ComponentScan(basePackageClasses = { ActorRepository.class }) @MapperScan(basePackageClasses = { ActorMapper.class }) public class MyBatisConfiguration extends AbstractFlywayMyBatisConfiguration { // datasource 용 properties (application.properties 에서 자동으로 정보를 읽어옴) @Inject DataSourceProperties dataSourceProperties; // mybatis 용 properties (application.properties 에서 자동으로 정보를 읽어옴) @Inject MybatisProperties mybatisProperties; @Override protected DatabaseSetting getDatabaseSetting() { return DatabaseSetting.builder() .driverClass(dataSourceProperties.getDriverClassName()) .jdbcUrl(dataSourceProperties.getUrl()) .build(); } @Override protected String getMyBatisConfigPath() { return mybatisProperties.getConfig(); } @Override protected String getMyBatisMapperPath() { return mybatisProperties.getMapperLocations()[0]; } } 2016-10-12KESTI 개발팀 세미나 11 XML Config 와 장단점 비교
  • 12. Spring Boot application.properties ### DataSource spring.datasource.driver-class-name=org.h2.Driver spring.datasource.jdbc-url=jdbc:h2:mem spring.datasource.username=sa spring.datasource.password= ### MyBatis mybatis.config=mybatis/mybatis-config.xml mybatis.mapper-locations=mybatis/mappers/**/*Mapper.xml mybatis.executor-type=simple ### Logging logging.level.root=info logging.level.kr.kesti.mybatis.examples=debug 2016-10-12KESTI 개발팀 세미나 12
  • 13. Database Setup by Flyway /** * Flyway 를 이용한 DB Migration 을 수행하도록 합니다. * * @param dataSource DataSource * @return {@link Flyway} 인스턴스 */ @Bean(initMethod = "migrate") protected Flyway flyway(DataSource dataSource) { Flyway flyway = new Flyway(); flyway.setDataSource(dataSource); if (cleanDatabaseForTest()) { flyway.clean(); } return flyway; } CREATE TABLE Actors ( id SERIAL PRIMARY KEY, firstname VARCHAR(64), lastname VARCHAR(64) ); INSERT INTO Actors (firstname, lastname) VALUES ('Sunghyouk', 'Bae'); INSERT INTO Actors (firstname, lastname) VALUES ('Misook', 'Kwon'); INSERT INTO Actors (firstname, lastname) VALUES ('Jehyoung', 'Bae'); INSERT INTO Actors (firstname, lastname) VALUES ('Jinseok', 'Kwon'); INSERT INTO Actors (firstname, lastname) VALUES ('Kildong', 'Hong'); 2016-10-12KESTI 개발팀 세미나 13
  • 14. Configuration Test @Slf4j @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { MyBatisConfiguration.class }) public class MyBatisConfigurationTest { @Inject ActorMapper actorMapper; @Inject ActorRepository actorRepository; @Inject private SqlSessionFactory sf; @Test public void testConfiguration() { assertThat(actorMapper).isNotNull(); assertThat(actorRepository).isNotNull(); assertThat(sf).isNotNull(); } } 2016-10-12KESTI 개발팀 세미나 14
  • 15. Repository Test @Slf4j @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { MyBatisConfiguration.class }) public class ActorRepositoryTest { @Inject ActorRepository actorRepo; private static final String FIRST_NAME = "Sunghyouk"; @Test public void testConfiguration() { assertThat(actorRepo).isNotNull(); } @Test public void testFindByFirstname() { Actor actor = actorRepo.findByFirstname(FIRST_NAME); assertThat(actor).isNotNull(); } @Test public void testFindByFirstnameWithXmlMapper() { Actor actor = actorRepo.findByFirstnameWithXmlMapper(FIRST_NAME); assertThat(actor).isNotNull(); } @Test public void testFindAll() { List<Actor> actors = actorRepo.findAll(); assertThat(actors.size()).isGreaterThan(0); } @Test public void testInsertActor() { String firstname = "mybatis"; Actor actor = Actor.of(null, firstname, "kesti"); int rowCount = actorRepo.insertActor(actor); log.debug("rowCount={}", rowCount); actor = actorRepo.findByFirstname(firstname); log.debug("actor={}", actor); assertThat(actor).isNotNull(); assertThat(actor.getFirstname()).isEqualTo(firstname); actorRepo.deleteById(actor.getId()); } } 2016-10-12KESTI 개발팀 세미나 15
  • 16. Flyway Evolve your Database Schema easily and reliably across all your instances 2016-10-12KESTI 개발팀 세미나 16
  • 17. Code 관리는 git 2016-10-12KESTI 개발팀 세미나 17 DB 형상 관리는?
  • 18. DB Schema Control by Dev Step 2016-10-12KESTI 개발팀 세미나 18
  • 19. DB Schema Version Control 2016-10-12KESTI 개발팀 세미나 19
  • 20. QueryDSL Unified Queries for Java with Typesafe 2016-10-12KESTI 개발팀 세미나 20
  • 21. QueryDSL 개요 • 질의어를 문자열이 아닌 Java Code로 표현 • Query문 – type check 불가 / 실행 전에는 오류 검출 불가 • Java Code는 • Compile Error를 미리 검출 • Code assistant 활용 100% • Refactoring 용이 • 다양한 저장소에 대한 일관된 질의어 제작 가능 • Collection, RDBMS, MongoDB, Lucene … • .NET 의 LINQ 같은 목적 (Langunage-INtegrated Query) • 참고 : 한글 매뉴얼 (단 3.4.0 기준임. 4.x 는 package 명이 달라졌음) 2016-10-12KESTI 개발팀 세미나 21
  • 22. QueryDSL 적용 범위 JPA (Java Persistence API) JDO (Java Data Object) SQL Lucence MongoDB Collections QueryDSL RDBMS ORM Lucene (search engine) MongoD B List / Map 2016-10-12KESTI 개발팀 세미나 22
  • 23. QueryDSL for SQL • Select • Join (innerJoin, join, leftJoin, rightJoin, fullJoin) • group by / having • order by • limit / offset / restrict • subquery • Window functions • Common Table Expression (CTE) • Insert • Update • Delete 2016-10-12KESTI 개발팀 세미나 23
  • 24. SELECT with Projections 2016-10-12KESTI 개발팀 세미나 24 QActors $ = QActors.actors; List<Tuple> rows = query.select($.id, $.firstname, $.lastname) .from($) .fetch(); QActors $ = QActors.actors; List<Actor> actors = query.select(Projections.constructor(Actor.class, $.id, $.firstname, $.lastname)) .from($) .fetch();
  • 25. SELECT – Filter, GroupBy 2016-10-12KESTI 개발팀 세미나 25 Actor actor = query.select(Projections.constructor(Actor.class, $.id, $.firstname, $.lastname)) .from($) .where($.lastname.eq("Bae")) .fetchFirst(); List<Tuple> rows = query.select($.lastname, $.lastname.count().as("cnt")) .from($) .groupBy($.lastname) .fetch();
  • 26. SELECT : Subquery 2016-10-12KESTI 개발팀 세미나 26 QActors $ = QActors.actors; QActors $2 = new QActors("$2"); SQLQuery<Actor> sq = query.select(Projections.constructor(Actor.class, $.id, $.firstname, $.lastname)) .from($) .where($.id.eq(SQLExpressions.select($2.id.max()).from($2))); List<Actor> actors = sq.fetch();
  • 27. CUD 2016-10-12KESTI 개발팀 세미나 27 QActors $ = QActors.actors; long inserted = query.insert($) .columns($.firstname, $.lastname) .values("querydsl", "examples") .execute(); long updated = query.update($) .set($.lastname, "updated examples") .where($.firstname.eq("querydsl")) .execute(); long deleted = query.delete($) .where($.firstname.eq("querydsl")) .execute();
  • 28. CUD Batch Execution 2016-10-12KESTI 개발팀 세미나 28 QActors $ = QActors.actors; int COUNT = 100; // INSERT SQLInsertClause insertClause = query.insert($); for (int i = 0; i < COUNT; i++) { insertClause.set($.firstname, "firstname-" + i) .set($.lastname, "lastname-" + i) .addBatch(); } long insertedCount = insertClause.execute(); // UPDATE SQLUpdateClause updateClause = query.update($); for (int i = 0; i < COUNT; i++) { updateClause.set($.firstname, "updated-firstname-" + i) .where($.lastname.eq("lastname-" + i)) .addBatch(); } long updatedCount = updateClause.execute(); // DELETE SQLDeleteClause deleteClause = query.delete($); for (int i = 0; i < COUNT; i++) { deleteClause.where($.firstname.eq("updated-firstname-" + i)) .addBatch(); } long deletedCount = deleteClause.execute();
  • 29. QueryDSL Dependency 2016-10-12KESTI 개발팀 세미나 29 <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-sql</artifactId> <version>${com.querydsl.version}</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-sql-spring</artifactId> <version>${com.querydsl.version}</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-sql-codegen</artifactId> <version>${com.querydsl.version}</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-spatial</artifactId> <version>${com.querydsl.version}</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-sql-spatial</artifactId> <version>${com.querydsl.version}</version> </dependency>
  • 30. QueryDSL APT 2016-10-12KESTI 개발팀 세미나 30 <plugin> <groupId>com.querydsl</groupId> <artifactId>querydsl-maven-plugin</artifactId> <version>${com.querydsl.version}</version> <executions> <execution> <goals> <goal>export</goal> </goals> </execution> </executions> <configuration> <jdbcDriver>org.postgresql.Driver</jdbcDriver> <jdbcUrl>jdbc:postgresql://localhost/querydsl</jdbcUrl> <jdbcUser>root</jdbcUser> <jdbcPassword>root</jdbcPassword> <packageName>kesti4j.data.querydsl.models</packageName> <sourceFolder>${project.basedir}/target/generated-sources/java</sourceFolder> <targetFolder>${project.basedir}/target/generated-sources/java</targetFolder> <spatial>true</spatial> </configuration> <dependencies> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.4-1206-jdbc42</version> </dependency> </dependencies> </plugin>
  • 31. QueryDSL Generated Code 2016-10-12KESTI 개발팀 세미나 31 /** * QActors is a Querydsl query type for QActors */ @Generated("com.querydsl.sql.codegen.MetaDataSerializer") public class QActors extends RelationalPathSpatial<QActors> { private static final long serialVersionUID = 822224394; public static final QActors actors = new QActors("actors"); public final StringPath firstname = createString("firstname"); public final NumberPath<Integer> id = createNumber("id", Integer.class); public final StringPath lastname = createString("lastname"); public final com.querydsl.sql.PrimaryKey<QActors> actorsPkey = createPrimaryKey(id); public QActors(String variable) { super(QActors.class, forVariable(variable), "public", "actors"); addMetadata(); } public QActors(String variable, String schema, String table) { super(QActors.class, forVariable(variable), schema, table); addMetadata(); } public QActors(Path<? extends QActors> path) { super(path.getType(), path.getMetadata(), "public", "actors"); addMetadata(); } public QActors(PathMetadata metadata) { super(QActors.class, metadata, "public", "actors"); addMetadata(); } public void addMetadata() { addMetadata(firstname, ColumnMetadata.named("firstname").withIndex(2).ofType(Types.VARCHAR).withSize(64)); addMetadata(id, ColumnMetadata.named("id").withIndex(1).ofType(Types.INTEGER).withSize(10).notNull()); addMetadata(lastname, ColumnMetadata.named("lastname").withIndex(3).ofType(Types.VARCHAR).withSize(64)); } }