SlideShare una empresa de Scribd logo
1 de 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));
}
}

Más contenido relacionado

La actualidad más candente

Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introductionJonathan Holloway
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework tola99
 
Introduction to Spring Framework and Spring IoC
Introduction to Spring Framework and Spring IoCIntroduction to Spring Framework and Spring IoC
Introduction to Spring Framework and Spring IoCFunnelll
 
Modern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and ThymeleafModern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and ThymeleafLAY Leangsros
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVCDzmitry Naskou
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with SpringJoshua Long
 
Spring boot
Spring bootSpring boot
Spring bootsdeeg
 
Spring Framework
Spring FrameworkSpring Framework
Spring Frameworknomykk
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework Serhat Can
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootJosué Neis
 
Spring: Overview do framework mais popular para desenvolvimento em Java
Spring: Overview do framework mais popular para desenvolvimento em JavaSpring: Overview do framework mais popular para desenvolvimento em Java
Spring: Overview do framework mais popular para desenvolvimento em JavaMariana de Azevedo Santos
 
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
 
Microservices Design Patterns | Edureka
Microservices Design Patterns | EdurekaMicroservices Design Patterns | Edureka
Microservices Design Patterns | EdurekaEdureka!
 

La actualidad más candente (20)

Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introduction
 
Spring Web MVC
Spring Web MVCSpring Web MVC
Spring Web MVC
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework
 
Spring Core
Spring CoreSpring Core
Spring Core
 
Introduction to Spring Framework and Spring IoC
Introduction to Spring Framework and Spring IoCIntroduction to Spring Framework and Spring IoC
Introduction to Spring Framework and Spring IoC
 
Spring beans
Spring beansSpring beans
Spring beans
 
Modern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and ThymeleafModern Java web applications with Spring Boot and Thymeleaf
Modern Java web applications with Spring Boot and Thymeleaf
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
Spring boot
Spring bootSpring boot
Spring boot
 
Spring Framework
Spring FrameworkSpring Framework
Spring Framework
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Spring boot
Spring bootSpring boot
Spring boot
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBoot
 
Spring Cloud Config
Spring Cloud ConfigSpring Cloud Config
Spring Cloud Config
 
Spring: Overview do framework mais popular para desenvolvimento em Java
Spring: Overview do framework mais popular para desenvolvimento em JavaSpring: Overview do framework mais popular para desenvolvimento em Java
Spring: Overview do framework mais popular para desenvolvimento em Java
 
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
 
Spring jdbc
Spring jdbcSpring jdbc
Spring jdbc
 
Microservices Design Patterns | Edureka
Microservices Design Patterns | EdurekaMicroservices Design Patterns | Edureka
Microservices Design Patterns | Edureka
 

Destacado

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
 

Destacado (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
 

Similar a 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
 

Similar a 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
 

Más de 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
 

Más de 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
 

Último

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...masabamasaba
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
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
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
%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
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
 
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
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
%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
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 

Último (20)

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
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...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
%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
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
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
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%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
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 

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)); } }