SlideShare una empresa de Scribd logo
1 de 106
Descargar para leer sin conexión
本日のお話
MyBatis
数億を超える
社内きっての大規模プロジェクト
可用性 99.99%
 絶対に止まらないシステム
データ件数 2億件
 ビックデータへの対応
連携装置 3万台
 負荷に対応できるシステム
このプロジェクトに
MyBatisで挑みました!
(`・ω・)
本日は
・MyBatisの紹介
・プロジェクトに適用した
 MyBatisの技術事例
についてお話をしよう
と思います!
つまりですね
これは、高可用・大規模プロジェクトに挑んだ
知られざるシステムアーキテクトの話である
主題歌「地上の星」
中島 みゆき
一般的な中堅SIer
社内きっての
大規模プロジェクト
可用性
99.99%
許される年間停止時間
53分未満
現行システムに性能遅延
連
携
装
置
3
万
台
デー
タ
件
数
 
 
2
億
件
以
上
!
移
行
時
も
シ
ス
テ
ム
停
止
は
許
さ
れ
な
い
!
インフルエンザ
の猛威!
次々倒れるチームメンバ
(平均年齢35才)
新チーム結成
シスアーキ
の意地!
負荷テストで
システムダウン!
迫られるO/R Mapperの
選択
MyBatisで行く!
押し寄せる
寝不足
ドラクエX
挑め!99.99%!
~大規模プロジェクトに見る
 MyBatisの技術事例~
presents by
すいません
お待たせしました
m(__)m
オープニングは前回の
使いまわしです。
# もう一度使ってみたかった
ちなみに
可用性 99.99%!
データ件数 2億件!
連携装置 3万台!
をどのように実現したのか
可用性 99.99%!
データ件数 2億件!
連携装置 3万台!
をどのように実現したのか
などの話はしません
話すのはMyBatisの内容ね
難しい話はできません
ごめんね
MyBatis
自己紹介自己紹介
<名前>
こざけさんじゅうはっさい
<メッセージ>
はい、ビールが好きです!
Twitter@s_kozake
<最近のお気に入り>
ニャンコ先生
MyBatis
MyBatis #とは
MyBatis入門
MyBatisの活用事例
まとめ
AgendaAgenda
MyBatis
MyBatis #とは
MyBatis入門
MyBatisの活用事例
まとめ
AgendaAgenda
MyBatis
MyBatis #とは
・XMLまたはアノテーションを用いてストアドプロシージャ
 やSQL文をオブジェクトと紐付ける永続性フレームワーク
・Apache License 2.0によるオープンソースソフトウェアとして提供
・以前はiBATISとして知られていた
wikiより転載
http://ja.wikipedia.org/wiki/MyBatis
MyBatis
MyBatis #とは
・他のO/Rマッピングフレームワークとは異なりデータベースと
 オブジェクトをマッピングするのではなく、SQL文とオブジェクト
 のマッピングを行う
・レガシーな環境や非正規化されたデータベース、またはSQL文
 の実行を完全に制御したい場合に、よい選択肢となる
・一番の特徴は、XMLに記述したSQL文を普通のオブジェクト
 と組み合わせられることである
wikiより転載
http://ja.wikipedia.org/wiki/MyBatis
特徴
MyBatis
MyBatis #とは
・他のO/Rマッピングフレームワークとは異なりデータベースと
 オブジェクトをマッピングするのではなく、SQL文とオブジェクト
 のマッピングを行う
・レガシーな環境や非正規化されたデータベース、またはSQL文
 の実行を完全に制御したい場合に、よい選択肢となる
・一番の特徴は、XMLに記述したSQL文を普通のオブジェクト
 と組み合わせられることである
wikiより転載
http://ja.wikipedia.org/wiki/MyBatis
特徴
プロジェクトにMyBatisを
採用した理由は
この特徴が大きいです。
MyBatis
MyBatis #とは
MyBatis入門
MyBatisの活用事例
まとめ
AgendaAgenda
MyBatis
MyBatis入門
・「例示は理解の試金石」 by 数学ガール
・MyBatisのSimpleなサンプル実装をMyBatisの概念図と
 紐付けて示します。
MyBatis
MyBatis #とは
用意したDB
ID INT (PK)
NAME VARCHAR(100)
SEX CHAR(1)
COMMENT CLOB
CREATED TIMESTAMP
ユーザ(USER)
ID INT (PK)
NAME VARCHAR(100)
アイテム(ITEM)
USER_ID INT (PK)
ITEM_ID INT (PK)
ユーザ所有アイテム
(USER_BELONG_ITEMS)1
*
1
*
MyBatis
MyBatis入門
MyBatis
MyBatis入門
MyBatisの設定ファイル
DB接続定義やMapper SQL Statementなどの定義
MyBatis
MyBatis入門
MyBatisの設定ファイル
DB接続定義やMapper SQL Statementなどの定義
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration >
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=orm"/>
<property name="username" value="ORM"/>
<property name="password" value="orm"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sample/sql/UserMap.xml" />
<mapper class="sample.mapper.ItemMapper" />
</mappers>
</configuration>
MyBatis
MyBatis入門
MyBatisの設定ファイル
DB接続定義やMapper SQL Statementなどの定義
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration >
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=orm"/>
<property name="username" value="ORM"/>
<property name="password" value="orm"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sample/sql/UserMap.xml" />
<mapper class="sample.mapper.ItemMapper" />
</mappers>
</configuration>
Databaseへの接続設定
MyBatis
MyBatis入門
MyBatisの設定ファイル
DB接続定義やMapper SQL Statementなどの定義
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration >
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=orm"/>
<property name="username" value="ORM"/>
<property name="password" value="orm"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="sample/sql/UserMap.xml" />
<mapper class="sample.mapper.ItemMapper" />
</mappers>
</configuration>
SqlMapの情報
MyBatis
MyBatis入門 SQLとオブジェクトとのマッピング定義
MyBatis
MyBatis入門 SQLとオブジェクトとのマッピング定義
<?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="sample.mapper.UserMapper" >
<select id="selectUser" resultType="sample.entity.User" >
select * from USER where id =#{id}
</select>
</mapper>
MyBatis
MyBatis入門 SQLとオブジェクトとのマッピング定義
<?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="sample.mapper.UserMapper" >
<select id="selectUser" resultType="sample.entity.User" >
select * from USER where id =#{id}
</select>
</mapper>
Sqlの定義
パラメータや戻り値との
Mapping指定
MyBatis
MyBatis入門
Javaオブジェクト
MyBatis
MyBatis入門
Javaオブジェクト
public class User {
private Integer id;
private String name;
private String sex;
private Date created;
private String comment;
// Define setter and getter
}
public class Item {
private Integer id;
private String name;
// Define setter and getter
}
MyBatis
MyBatis入門
ユーザーコード
MyBatis
MyBatis入門
ユーザーコード
public class MapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init() throws IOException {
String resource = "sample/context/sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1() {
SqlSession session = sqlSessionFactory.openSession();
try {
User user = (User) session.selectOne("sample.mapper.UserMapper.selectUser", 1);
assertThat(user.getName(), is("小酒"));
} finally {
session.close();
}
}
}
MyBatis
MyBatis入門
ユーザーコード
public class MapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init() throws IOException {
String resource = "sample/context/sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1() {
SqlSession session = sqlSessionFactory.openSession();
try {
User user = (User) session.selectOne("sample.mapper.UserMapper.selectUser", 1);
assertThat(user.getName(), is("小酒"));
} finally {
session.close();
}
}
}
sqlMapConfigの設定から
sqlSessionFactoryを生成
通常システム起動時に行えばよい
MyBatis
MyBatis入門
ユーザーコード
public class MapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init() throws IOException {
String resource = "sample/context/sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1() {
SqlSession session = sqlSessionFactory.openSession();
try {
User user = (User) session.selectOne("sample.mapper.UserMapper.selectUser", 1);
assertThat(user.getName(), is("小酒"));
} finally {
session.close();
}
}
}
sqlSessionFactoryから
SqlSessionオブジェクトの生成
SqlSessionオブジェクトは
トランザクション制御から
Query実行、Mapper提供
などのAPIを提供する、
MyBatisの主要オブジェクト
MyBatis
MyBatis入門
ユーザーコード
@Test
public void test1() {
SqlSession session = sqlSessionFactory.openSession();
try {
User user = (User) session.selectOne("sample.mapper.UserMapper.selectUser", 1);
assertThat(user.getName(), is("小酒"));
} finally {
session.close();
}
}
}
<mapper namespace="sample.mapper.UserMapper" >
<select id="selectUser" resultType="sample.entity.User" >
select * from USER where id =#{id}
</select>
</mapper>
SqlMapで定義されたSQL
を呼び出し、オブジェクトに
Mappingした結果を受け取れる。
MyBatis
MyBatis入門
ユーザーコード
@Test
public void test2() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.selectUser(1);
assertThat(user.getName(), is("小酒"));
} finally {
session.close();
}
}
public interface UserMapper {
User selectUser(int id);
}
MyBatis
MyBatis入門
ユーザーコード
@Test
public void test2() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.selectUser(1);
assertThat(user.getName(), is("小酒"));
} finally {
session.close();
}
}
public interface UserMapper {
User selectUser(int id);
}
Javaインタフェースを定義して、
型安全にSql定義と紐付けることも可能。
内部ではProxyを用いて実現している。
MyBatis
MyBatis入門
ユーザーコード
@Test
public void test3() {
SqlSession session = sqlSessionFactory.openSession();
try {
ItemMapper itemMapper = session.getMapper(ItemMapper.class);
List<Item> items = itemMapper.selectByName("天空%");
assertThat(items.size(), is(2));
assertThat(items.get(0).getName(), is("天空の剣"));
assertThat(items.get(1).getName(), is("天空の鎧"));
} finally {
session.close();
}
}
public interface ItemMapper {
@Select("select * from ITEM where name like #{id} order by id")
List<Item> selectByName(String name);
}
MyBatis
MyBatis入門
ユーザーコード
@Test
public void test3() {
SqlSession session = sqlSessionFactory.openSession();
try {
ItemMapper itemMapper = session.getMapper(ItemMapper.class);
List<Item> items = itemMapper.selectByName("天空%");
assertThat(items.size(), is(2));
assertThat(items.get(0).getName(), is("天空の剣"));
assertThat(items.get(1).getName(), is("天空の鎧"));
} finally {
session.close();
}
}
public interface ItemMapper {
@Select("select * from ITEM where name like #{id} order by id")
List<Item> selectByName(String name);
}
アノーテーションを用いてSQLを定義
することも可能。
MyBatis
・MyBatisにはデータベースのスキーマ情報を元にソースを自動生成
 してくれるGeneratorがある。
・自動生成されるソースは次のとおり。
 ・Entityオブジェクト
 ・Mapper XML
 ・Mapperインタフェース
 ・Criteriaオブジェクト
https://github.com/mybatis/generator
自動生成
MyBatis入門
MyBatis
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成設定(XMLファイル)
自動生成リソース
MyBatis入門
MyBatis
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成設定(XMLファイル)
自動生成リソース
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<jdbcConnection driverClass="org.h2.Driver"
connectionURL="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=hoge"
userId="ORM" password="orm">
</jdbcConnection>
<javaModelGenerator targetPackage="sample.entity"
targetProject="gen" />
<sqlMapGenerator targetPackage="sample.sql"
targetProject="gen" />
<javaClientGenerator targetPackage="sample.mapper"
targetProject="gen" type="XMLMAPPER" />
<table tableName="USER" />
<table tableName="ITEM" />
</context>
</generatorConfiguration>
MyBatis入門
MyBatis
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成設定(XMLファイル)
自動生成リソース
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<jdbcConnection driverClass="org.h2.Driver"
connectionURL="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=hoge"
userId="ORM" password="orm">
</jdbcConnection>
<javaModelGenerator targetPackage="sample.entity"
targetProject="gen" />
<sqlMapGenerator targetPackage="sample.sql"
targetProject="gen" />
<javaClientGenerator targetPackage="sample.mapper"
targetProject="gen" type="XMLMAPPER" />
<table tableName="USER" />
<table tableName="ITEM" />
</context>
</generatorConfiguration>
MyBatis入門
自動生成するためのスキーマ定義を提供する
Databaseへの接続定義
MyBatis
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成設定(XMLファイル)
自動生成リソース
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<jdbcConnection driverClass="org.h2.Driver"
connectionURL="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=hoge"
userId="ORM" password="orm">
</jdbcConnection>
<javaModelGenerator targetPackage="sample.entity"
targetProject="gen" />
<sqlMapGenerator targetPackage="sample.sql"
targetProject="gen" />
<javaClientGenerator targetPackage="sample.mapper"
targetProject="gen" type="XMLMAPPER" />
<table tableName="USER" />
<table tableName="ITEM" />
</context>
</generatorConfiguration>
MyBatis入門
生成リソースのpackageや生成フォルダ、
生成リソースの種類などを定義
MyBatis
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成設定(XMLファイル)
自動生成リソース
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<jdbcConnection driverClass="org.h2.Driver"
connectionURL="jdbc:h2:tcp://localhost/C:MyFilesormdaoh2db;schema=hoge"
userId="ORM" password="orm">
</jdbcConnection>
<javaModelGenerator targetPackage="sample.entity"
targetProject="gen" />
<sqlMapGenerator targetPackage="sample.sql"
targetProject="gen" />
<javaClientGenerator targetPackage="sample.mapper"
targetProject="gen" type="XMLMAPPER" />
<table tableName="USER" />
<table tableName="ITEM" />
</context>
</generatorConfiguration>
MyBatis入門
生成するテーブルやビューを指定
MyBatis
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成設定(XMLファイル)
自動生成リソース
MyBatis入門
C:.
├─entity
│ Item.java
│ ItemExample.java
│ User.java
│ UserExample.java
│
├─mapper
│ ItemMapper.java
│ UserMapper.java
│
└─sql
ItemMapper.xml
UserMapper.xml
MyBatis
public class MapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init() throws IOException {
String resource = "sample/context/sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.selectByPrimaryKey(1);
assertThat(user.getName(), is("小酒"));
assertThat(user.getComment(), is("こんにちは"));
} finally {
session.close();
}
}
}
MyBatis入門
MyBatis
public class MapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init() throws IOException {
String resource = "sample/context/sqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void test1() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.selectByPrimaryKey(1);
assertThat(user.getName(), is("小酒"));
assertThat(user.getComment(), is("こんにちは"));
} finally {
session.close();
}
}
}
MyBatis入門
主キーによる検索メソッドが
自動生成されている。
MyBatis
@Test
public void test2() {
SqlSession session = sqlSessionFactory.openSession();
try {
ItemMapper itemMapper = session.getMapper(ItemMapper.class);
ItemExample itemEx = new ItemExample();
itemEx.createCriteria().andNameLike("天空%");
itemEx.or().andNameEqualTo("こんぼう");
itemEx.setOrderByClause("ID desc");
List<Item> items = itemMapper.selectByExample(itemEx);
assertThat(items.size(), is(3));
assertThat(items.get(0).getName(), is("天空の鎧"));
assertThat(items.get(1).getName(), is("天空の剣"));
assertThat(items.get(2).getName(), is("こんぼう"));
} finally {
session.close();
}
}
}
MyBatis入門
MyBatis
@Test
public void test2() {
SqlSession session = sqlSessionFactory.openSession();
try {
ItemMapper itemMapper = session.getMapper(ItemMapper.class);
ItemExample itemEx = new ItemExample();
itemEx.createCriteria().andNameLike("天空%");
itemEx.or().andNameEqualTo("こんぼう");
itemEx.setOrderByClause("ID desc");
List<Item> items = itemMapper.selectByExample(itemEx);
assertThat(items.size(), is(3));
assertThat(items.get(0).getName(), is("天空の鎧"));
assertThat(items.get(1).getName(), is("天空の剣"));
assertThat(items.get(2).getName(), is("こんぼう"));
} finally {
session.close();
}
}
}
MyBatis入門
Criteriaによる検索条件を指定可能。上記の例では
select * from ITEM
where name like '天空%' or name = 'こんぼう'
ordery by ID desc
のクエリーが発行されている。
MyBatis
@Test
public void test3() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
UserExample userEx = new UserExample();
userEx.createCriteria().andNameEqualTo("小酒");
List<User> users = userMapper.selectByExample(userEx);
assertThat(users.size(), is(1));
assertThat(users.get(0).getName(), is("小酒"));
assertThat(users.get(0).getComment(), is(nullValue()));
users = userMapper.selectByExampleWithBLOBs(userEx);
assertThat(users.get(0).getComment(), is("こんにちは"));
} finally {
session.close();
}
}
MyBatis入門
MyBatis
@Test
public void test3() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
UserExample userEx = new UserExample();
userEx.createCriteria().andNameEqualTo("小酒");
List<User> users = userMapper.selectByExample(userEx);
assertThat(users.size(), is(1));
assertThat(users.get(0).getName(), is("小酒"));
assertThat(users.get(0).getComment(), is(nullValue()));
users = userMapper.selectByExampleWithBLOBs(userEx);
assertThat(users.get(0).getComment(), is("こんにちは"));
} finally {
session.close();
}
}
MyBatis入門
テーブルにBlobやClobなどのLarge Object情報が
ある場合、BlobありとBlobなしの二種類の
検索方法が自動生成で用意される。
※性能的な理由によるものと思われる。
MyBatis
@Test
public void test4() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setId(3); user.setName("にゃんこ先生"); user.setSex("M"); user.setCreated(new java.util.Date());
userMapper.insert(user);
session.commit();
assertThat(userMapper.countByExample(new UserExample()), is(3));
  :
} finally {
session.close();
}
}
MyBatis入門
MyBatis
@Test
public void test4() {
SqlSession session = sqlSessionFactory.openSession();
try {
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setId(3); user.setName("にゃんこ先生"); user.setSex("M"); user.setCreated(new java.util.Date());
userMapper.insert(user);
session.commit();
assertThat(userMapper.countByExample(new UserExample()), is(3));
  :
} finally {
session.close();
}
}
MyBatis入門
追加はinsertメソッドで
sessionオブジェクトのcommitメソッドおよび
rollbackメソッドでトランザクションを制御できる。
MyBatis
@Test
public void test4() {
SqlSession session = sqlSessionFactory.openSession();
try {
  :
user.setComment("にゃー!");
userMapper.updateByPrimaryKeyWithBLOBs(user);
session.commit();
user = userMapper.selectByPrimaryKey(3);
assertThat(user.getName(), is("にゃんこ先生"));
assertThat(user.getComment(), is("にゃー!"));
userMapper.deleteByPrimaryKey(3);
session.commit();
assertThat(userMapper.countByExample(new UserExample()), is(2));
} finally {
session.close();
}
}
MyBatis入門
MyBatis
@Test
public void test4() {
SqlSession session = sqlSessionFactory.openSession();
try {
  :
user.setComment("にゃー!");
userMapper.updateByPrimaryKeyWithBLOBs(user);
session.commit();
user = userMapper.selectByPrimaryKey(3);
assertThat(user.getName(), is("にゃんこ先生"));
assertThat(user.getComment(), is("にゃー!"));
userMapper.deleteByPrimaryKey(3);
session.commit();
assertThat(userMapper.countByExample(new UserExample()), is(2));
} finally {
session.close();
}
}
MyBatis入門
更新はupdateメソッドで
Blobあり/なしで二種類のメソッドが自動生成されている。
主キーを用いた更新や、Criteriaを用いた条件による更新が可能
MyBatis
@Test
public void test4() {
SqlSession session = sqlSessionFactory.openSession();
try {
  :
user.setComment("にゃー!");
userMapper.updateByPrimaryKeyWithBLOBs(user);
session.commit();
user = userMapper.selectByPrimaryKey(3);
assertThat(user.getName(), is("にゃんこ先生"));
assertThat(user.getComment(), is("にゃー!"));
userMapper.deleteByPrimaryKey(3);
session.commit();
assertThat(userMapper.countByExample(new UserExample()), is(2));
} finally {
session.close();
}
}
MyBatis入門
削除はdeleteメソッドで
主キーを用いた削除や、Criteriaを用いた条件による削除が可能
MyBatis
MyBatis入門
More infomation
・公式サイトの日本語情報が充実
・http://mybatis.github.io/mybatis-3/ja/
MyBatis
MyBatis #とは
MyBatis入門
MyBatisの活用事例
まとめ
AgendaAgenda
MyBatis
・MyBatisは多機能なO/Rマッパーなので、プロジェクトに応じて
 様々な使い方ができます。
MyBatisの活用事例
・ここでは、実際のプロジェクトでMyBatisを活用した際のいくつか
 の技術事例を紹介します。
MyBatis
Sessionを管理したい
・SqlSessionのAPIでMapperオブジェクトの取得や
 commit/rollbackを制御する。
・処理間(メソッド間)でSqlSessionの引き回しはしたくない。
MyBatisの活用事例
MyBatis
Sessionを管理したい
・SqlSessionのAPIでMapperオブジェクトの取得や
 commit/rollbackを制御する。
・処理間(メソッド間)でSqlSessionの引き回しはしたくない。
MyBatisの活用事例
・SqlSessionManagerを使うことでスレッド単位でSqlSession
 を管理できる。
MyBatis
Sessionを管理したい
MyBatisの活用事例
private static SqlSessionManager sessionManager;
@BeforeClass
public static void init() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sample/context/MapperConfig.xml");
sessionManager = SqlSessionManager.newInstance(new SqlSessionFactoryBuilder().build(inputStream));
}
@Before
public void before() { sessionManager.startManagedSession(); }
@After
public void after() { sessionManager.close(); }
@Test
public void test() {
UserMapper userMapper = sessionManager.getMapper(UserMapper.class);
User user = new User();
user.setId(3); user.setName("にゃんこ先生"); user.setSex("M"); user.setCreated(new java.util.Date());
userMapper.insert(user);
sessionManager.rollback();
assertThat(userMapper.countByExample(new UserExample()), is(2));
}
MyBatis
Sessionを管理したい
MyBatisの活用事例
private static SqlSessionManager sessionManager;
@BeforeClass
public static void init() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sample/context/MapperConfig.xml");
sessionManager = SqlSessionManager.newInstance(new SqlSessionFactoryBuilder().build(inputStream));
}
@Before
public void before() { sessionManager.startManagedSession(); }
@After
public void after() { sessionManager.close(); }
@Test
public void test() {
UserMapper userMapper = sessionManager.getMapper(UserMapper.class);
User user = new User();
user.setId(3); user.setName("にゃんこ先生"); user.setSex("M"); user.setCreated(new java.util.Date());
userMapper.insert(user);
sessionManager.rollback();
assertThat(userMapper.countByExample(new UserExample()), is(2));
}
SqlSessionFactoryからSqlSessionManagerを生成
通常、システム起動時に一度だけ生成すればいい。
MyBatis
Sessionを管理したい
MyBatisの活用事例
private static SqlSessionManager sessionManager;
@BeforeClass
public static void init() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sample/context/MapperConfig.xml");
sessionManager = SqlSessionManager.newInstance(new SqlSessionFactoryBuilder().build(inputStream));
}
@Before
public void before() { sessionManager.startManagedSession(); }
@After
public void after() { sessionManager.close(); }
@Test
public void test() {
UserMapper userMapper = sessionManager.getMapper(UserMapper.class);
User user = new User();
user.setId(3); user.setName("にゃんこ先生"); user.setSex("M"); user.setCreated(new java.util.Date());
userMapper.insert(user);
sessionManager.rollback();
assertThat(userMapper.countByExample(new UserExample()), is(2));
}
startManagedSessionメソッドの呼び出しで
内部的にSqlSessionインスタンスが生成され、
スレッドローカル変数で管理される。
MyBatis
Sessionを管理したい
MyBatisの活用事例
private static SqlSessionManager sessionManager;
@BeforeClass
public static void init() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("sample/context/MapperConfig.xml");
sessionManager = SqlSessionManager.newInstance(new SqlSessionFactoryBuilder().build(inputStream));
}
@Before
public void before() { sessionManager.startManagedSession(); }
@After
public void after() { sessionManager.close(); }
@Test
public void test() {
UserMapper userMapper = sessionManager.getMapper(UserMapper.class);
User user = new User();
user.setId(3); user.setName("にゃんこ先生"); user.setSex("M"); user.setCreated(new java.util.Date());
userMapper.insert(user);
sessionManager.rollback();
assertThat(userMapper.countByExample(new UserExample()), is(2));
}
SqlSessionManagerはSqlSessionインタフェースを
実装しているので、SqlSessionと同様のAPIを
提供。
MyBatis
文字化けに対処したい
・有名な「~」の文字化け
・MS932とSJISのUnicodeのマッピングの違いによって生じる。
MyBatisの活用事例
MyBatis
文字化けに対処したい
・有名な「~」の文字化け
・MS932とSJISのUnicodeのマッピングの違いによって生じる。
MyBatisの活用事例
・typeHandlerでUnicodeの文字変換を行うことで解決!
MyBatis
文字化けに対処したい
MyBatisの活用事例
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration >
:
<typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR" handler="hogedriven.StringTypeHandler"/>
<typeHandler javaType="String" jdbcType="CHAR" handler="hogedriven.StringTypeHandler"/>
</typeHandlers>
:
</configuration>
MyBatis
文字化けに対処したい
MyBatisの活用事例
public final class StringTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, convertTo(parameter));
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return convertTo(rs.getString(columnName));
}
:
private static final String convertTo(String str) {
StringBuffer result = new StringBuffer();
char c;
for (int i = 0; i < str.length(); i++) {
c = str.charAt(i);
switch (c) {
// WAVE DASH(~)
case 0x301c:
c = 0xff5e;
break;
default:
break;
}
result.append(c);
}
return result.toString();
}
}
MyBatis
文字化けに対処したい
MyBatisの活用事例
public final class StringTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, convertTo(parameter));
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return convertTo(rs.getString(columnName));
}
:
private static final String convertTo(String str) {
StringBuffer result = new StringBuffer();
char c;
for (int i = 0; i < str.length(); i++) {
c = str.charAt(i);
switch (c) {
// WAVE DASH(~)
case 0x301c:
c = 0xff5e;
break;
default:
break;
}
result.append(c);
}
return result.toString();
}
}
DBからのread/writeのタイミングで、それぞれの
文字エンコーダに応じてUnicodeの文字コードを
変更してやればいい。
MyBatis
違うスキーマから自動生成したい
・自動生成ソースを作成するデータベースの参照スキーマを
 実行環境とは別のものにしたい。
MyBatisの活用事例
DB
MyBatis Generater
Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
自動生成リソース
DB
自動生成用スキーマ
実行用スキーマ
MyBatis
違うスキーマから自動生成したい
・自動生成ソースを作成するデータベースの参照スキーマを
 実行環境とは別のものにしたい。
MyBatisの活用事例
・自動生成設定のtableタグにschema属性を指定する。
・それだけだと、生成されたSQLが指定されたschemaを指定
 したクエリとなるので、
  <property name="ignoreQualifiersAtRuntime" value="true"/>
 を指定する。
MyBatis
違うスキーマから自動生成したい
MyBatisの活用事例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
:
<table schema="orm" tableName="USER" >
<property name="ignoreQualifiersAtRuntime" value="true"/>
</table>
<table schema="orm" tableName="ITEM" >
<property name="ignoreQualifiersAtRuntime" value="true"/>
</table>
:
</context>
</generatorConfiguration>
MyBatis
MyBatisの活用事例
楽したい
・自動生成されたソースの検索APIが手続き型のAPI
 (コマンドクエリーAPI)で使いにくい
・自動生成されたソースはDAOのため、Entityに
 ビジネスロジックを書きたくないし、そもそも自動生成ソース
 を修正したくない。
・テーブルのメタデータだけでなく、SQLからも自動生成したい。
・てか、モデル層がないとコントローラ層にビジネスロジック
 ががが
MyBatis
MyBatisの活用事例
楽したい
・GeneratorのPluginでσ(゚∀゚)オレオレPlugin を実装!
・GeneratorはPluginを用いて自動生成ソースを追加/拡張できる!
・自動生成されたソースの検索APIが手続き型のAPI
 (コマンドクエリーAPI)で使いにくい
・自動生成されたソースはDAOのため、Entityに
 ビジネスロジックを書きたくないし、そもそも自動生成ソース
 を修正したくない。
・テーブルのメタデータだけでなく、SQLからも自動生成したい。
・てか、モデル層がないとコントローラ層にビジネスロジック
 ががが
MyBatis
MyBatisの活用事例
楽したい
DB
MyBatis Generater
+
σ(゚∀゚)オレオレPlugin Mapper XML
Entityオブジェクト
Criteriaオブジェクト
Mapperインターフェース
Modelオブジェクト
Queryオブジェクト
自動生成リソース
SQL
MapConfig XML
NEW
NEW
NEW
MyBatis
MyBatisの活用事例
自動生成クラス
Pluginで生成した
クラス
モデルクラス
自動生成ソースは修正しない!
楽したい
MyBatis
MyBatisの活用事例
楽したい
UserBelongItemsMapper.xml
User2itemq1.java
User2itemq1Example.java
User2itemq1Mapper.java
User2itemq1MoBase.java
User2itemq1Query.java
User2ItemQ1.sql
MapperConfig.xml
select user.*, item.id as item_id, item.name as item_name from USER user
join USER_BELONG_ITEMS blng on user.id = blng.user_id
join ITEM item on blng.item_id = item.id
MyBatis
MyBatisの活用事例
楽したい
UserBelongItemsMapper.xml
User2itemq1.java
User2itemq1Example.java
User2itemq1Mapper.java
User2itemq1MoBase.java
User2itemq1Query.java
User2ItemQ1.sql
MapperConfig.xml
select user.*, item.id as item_id, item.name as item_name from USER user
join USER_BELONG_ITEMS blng on user.id = blng.user_id
join ITEM item on blng.item_id = item.id
テーブルの結合条件を指定したSQLを指定
Viewを生成するイメージ
このSQLをPluginから実行し、ResultSetのメタ情報より
各種リソースを自動生成する。
MyBatis
MyBatisの活用事例
楽したい
UserBelongItemsMapper.xml
User2itemq1.java
User2itemq1Example.java
User2itemq1Mapper.java
User2itemq1MoBase.java
User2itemq1Query.java
User2ItemQ1.sql
MapperConfig.xml
:
<select id="selectByExample" resultMap="BaseResultMap"
parameterType="hogedriven.sample.dao.orm.entity.User2itemq1Example" >
select
<if test="distinct" >
distinct
</if>
<include refid="Base_Column_List" />
from (select user.*, item.id as item_id, item.name as item_name from USER user
join USER_BELONG_ITEMS blng on user.id = blng.user_id
join ITEM item on blng.item_id = item.id) User2ItemQ1
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null" >
order by ${orderByClause}
</if>
</select>
:
MyBatis
MyBatisの活用事例
楽したい
UserBelongItemsMapper.xml
User2itemq1.java
User2itemq1Example.java
User2itemq1Mapper.java
User2itemq1MoBase.java
User2itemq1Query.java
User2ItemQ1.sql
MapperConfig.xml
:
<select id="selectByExample" resultMap="BaseResultMap"
parameterType="hogedriven.sample.dao.orm.entity.User2itemq1Example" >
select
<if test="distinct" >
distinct
</if>
<include refid="Base_Column_List" />
from (select user.*, item.id as item_id, item.name as item_name from USER user
join USER_BELONG_ITEMS blng on user.id = blng.user_id
join ITEM item on blng.item_id = item.id) User2ItemQ1
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null" >
order by ${orderByClause}
</if>
</select>
:
副問い合わせによるSQLが生成された
MyBatis
MyBatisの活用事例
楽したい
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
:
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.SelectByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.UpdateByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.DeleteByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.CountByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.selectforupdate.SelectForUpdatePlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.custommapper.CustomMapperPlugin">
<property name="targetProject" value="sql/orm" />
</plugin>
<plugin type="hogedriven.mybatis.generator.plugins.model.ModelPlugin">
<property name="targetModelPackage" value="hogedriven.sample.app.model.orm" />
<property name="targetModelBasePackage" value="hogedriven.sample.dao.orm.model" />
<property name="targetQueryPackage" value="hogedriven.sample.dao.orm.query" />
<property name="targetModelProject" value="src_wrk/model" />
<property name="targetModelBaseProject" value="src_gen" />
<property name="targetQueryProject" value="src_gen" />
</plugin>
:
</context>
</generatorConfiguration>
MyBatis
MyBatisの活用事例
楽したい
<generatorConfiguration>
<context id="sample2" targetRuntime="MyBatis3">
:
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.SelectByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.UpdateByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.DeleteByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.queryby.CountByPlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.selectforupdate.SelectForUpdatePlugin" />
<plugin type="hogedriven.mybatis.generator.plugins.custommapper.CustomMapperPlugin">
<property name="targetProject" value="sql/orm" />
</plugin>
<plugin type="hogedriven.mybatis.generator.plugins.model.ModelPlugin">
<property name="targetModelPackage" value="hogedriven.sample.app.model.orm" />
<property name="targetModelBasePackage" value="hogedriven.sample.dao.orm.model" />
<property name="targetQueryPackage" value="hogedriven.sample.dao.orm.query" />
<property name="targetModelProject" value="src_wrk/model" />
<property name="targetModelBaseProject" value="src_gen" />
<property name="targetQueryProject" value="src_gen" />
</plugin>
:
</context>
</generatorConfiguration>
それぞれの用途に応じて作成したPlugin達
MyBatis
MyBatisの活用事例
楽したい
public class SampleTest {
@BeforeClass
public static void init() throws Exception { SqlContextManager.init("test"); }
@Before
public void before() { SqlContextManager.getContext("orm").beginTransaction(); }
@After
public void after() { SqlContextManager.getContext("orm").endTransaction(); }
@Test
public void test() {
UserMo userMo = UserMo.where().idEqualTo(1).fetchFirst(UserMo.class);
assertThat(userMo, is(notNullValue()));
assertThat(userMo.getName(), is("小酒"));
userMo.setName("こざけ");
userMo.saveSelective();
userMo.remove();
SqlContextManager.getContext("orm").rollback();
}
:
MyBatis
MyBatisの活用事例
楽したい
public class SampleTest {
@BeforeClass
public static void init() throws Exception { SqlContextManager.init("test"); }
@Before
public void before() { SqlContextManager.getContext("orm").beginTransaction(); }
@After
public void after() { SqlContextManager.getContext("orm").endTransaction(); }
@Test
public void test() {
UserMo userMo = UserMo.where().idEqualTo(1).fetchFirst(UserMo.class);
assertThat(userMo, is(notNullValue()));
assertThat(userMo.getName(), is("小酒"));
userMo.setName("こざけ");
userMo.saveSelective();
userMo.remove();
SqlContextManager.getContext("orm").rollback();
}
:
Pluginを用いて生成したモデルによる検索
流れるようなメソッドチェーンでSimpleに
かける!
MyBatis
MyBatisの活用事例
Demo
エル 知ってるか? Demoは大抵成功しない。
MyBatis
MyBatis #とは
MyBatis入門
MyBatisの活用事例
まとめ
AgendaAgenda
MyBatis
楽じゃなかった
Plugin作り過ぎたorz 。今は反省している・・
MyBatis
質問があれば

Más contenido relacionado

La actualidad más candente

オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
 

La actualidad más candente (20)

AWSで作る分析基盤
AWSで作る分析基盤AWSで作る分析基盤
AWSで作る分析基盤
 
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜 リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
リアルタイムサーバー 〜Erlang/OTPで作るPubSubサーバー〜
 
並行処理初心者のためのAkka入門
並行処理初心者のためのAkka入門並行処理初心者のためのAkka入門
並行処理初心者のためのAkka入門
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajpAt least onceってぶっちゃけ問題の先送りだったよね #kafkajp
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
 
NGINXをBFF (Backend for Frontend)として利用した話
NGINXをBFF (Backend for Frontend)として利用した話NGINXをBFF (Backend for Frontend)として利用した話
NGINXをBFF (Backend for Frontend)として利用した話
 
Kinesis + Elasticsearchでつくるさいきょうのログ分析基盤
Kinesis + Elasticsearchでつくるさいきょうのログ分析基盤Kinesis + Elasticsearchでつくるさいきょうのログ分析基盤
Kinesis + Elasticsearchでつくるさいきょうのログ分析基盤
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
 
MySQLレプリケーションあれやこれや
MySQLレプリケーションあれやこれやMySQLレプリケーションあれやこれや
MySQLレプリケーションあれやこれや
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
 
噛み砕いてKafka Streams #kafkajp
噛み砕いてKafka Streams #kafkajp噛み砕いてKafka Streams #kafkajp
噛み砕いてKafka Streams #kafkajp
 
トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法トランザクションをSerializableにする4つの方法
トランザクションをSerializableにする4つの方法
 
SpotBugs(FindBugs)による 大規模ERPのコード品質改善
SpotBugs(FindBugs)による 大規模ERPのコード品質改善SpotBugs(FindBugs)による 大規模ERPのコード品質改善
SpotBugs(FindBugs)による 大規模ERPのコード品質改善
 
Azureを頑張る理由と頑張り方(Cloud Skills Challenge 2022 winter 発表資料)
Azureを頑張る理由と頑張り方(Cloud Skills Challenge 2022 winter 発表資料)Azureを頑張る理由と頑張り方(Cloud Skills Challenge 2022 winter 発表資料)
Azureを頑張る理由と頑張り方(Cloud Skills Challenge 2022 winter 発表資料)
 
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design PatternAWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
 
爆速クエリエンジン”Presto”を使いたくなる話
爆速クエリエンジン”Presto”を使いたくなる話爆速クエリエンジン”Presto”を使いたくなる話
爆速クエリエンジン”Presto”を使いたくなる話
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 
CRDT in 15 minutes
CRDT in 15 minutesCRDT in 15 minutes
CRDT in 15 minutes
 
JCBの Payment as a Service 実現にむけたゼロベースの組織変革とテクニカル・イネーブラー(NTTデータ テクノロジーカンファレンス ...
JCBの Payment as a Service 実現にむけたゼロベースの組織変革とテクニカル・イネーブラー(NTTデータ テクノロジーカンファレンス ...JCBの Payment as a Service 実現にむけたゼロベースの組織変革とテクニカル・イネーブラー(NTTデータ テクノロジーカンファレンス ...
JCBの Payment as a Service 実現にむけたゼロベースの組織変革とテクニカル・イネーブラー(NTTデータ テクノロジーカンファレンス ...
 

Similar a システムアーキテクト~My batis編~

東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates
koichik
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
JPCERT Coordination Center
 

Similar a システムアーキテクト~My batis編~ (20)

jjugccc2018 app review postmortem
jjugccc2018 app review postmortemjjugccc2018 app review postmortem
jjugccc2018 app review postmortem
 
Android cleanarchitecture
Android cleanarchitectureAndroid cleanarchitecture
Android cleanarchitecture
 
東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates東京Node学園#3 Domains & Isolates
東京Node学園#3 Domains & Isolates
 
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
 
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみようWebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
WebRTC UserMedia Catalog: いろんなユーザメディア(MediaStream)を使ってみよう
 
20101018 JJUG CCC10 WindowsAzure
20101018 JJUG CCC10 WindowsAzure20101018 JJUG CCC10 WindowsAzure
20101018 JJUG CCC10 WindowsAzure
 
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
基礎から見直す ASP.NET MVC の単体テスト自動化方法 ~ Windows Azure 関連もあるかも~
 
Ajax basic
Ajax basicAjax basic
Ajax basic
 
Nginx
NginxNginx
Nginx
 
Building asp.net core blazor and elasticsearch elasticsearch using visual stu...
Building asp.net core blazor and elasticsearch elasticsearch using visual stu...Building asp.net core blazor and elasticsearch elasticsearch using visual stu...
Building asp.net core blazor and elasticsearch elasticsearch using visual stu...
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
 
Java/Androidセキュアコーディング
Java/AndroidセキュアコーディングJava/Androidセキュアコーディング
Java/Androidセキュアコーディング
 
実践 NestJS
実践 NestJS実践 NestJS
実践 NestJS
 
アドテク×Scala×パフォーマンスチューニング
アドテク×Scala×パフォーマンスチューニングアドテク×Scala×パフォーマンスチューニング
アドテク×Scala×パフォーマンスチューニング
 
Ajax 応用
Ajax 応用Ajax 応用
Ajax 応用
 
JPAの基礎と現場で役立つ開発Tips
JPAの基礎と現場で役立つ開発TipsJPAの基礎と現場で役立つ開発Tips
JPAの基礎と現場で役立つ開発Tips
 
Akkaの並行性
Akkaの並行性Akkaの並行性
Akkaの並行性
 
Implements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNetImplements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNet
 
Apache Torqueについて
Apache TorqueについてApache Torqueについて
Apache Torqueについて
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
 

Más de Shinichi Kozake

あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情についてあなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
Shinichi Kozake
 
MyBatisで流れるようなメソッドチェーン
MyBatisで流れるようなメソッドチェーンMyBatisで流れるようなメソッドチェーン
MyBatisで流れるようなメソッドチェーン
Shinichi Kozake
 

Más de Shinichi Kozake (20)

SIerアーキテクト視点でみたKotlinの紹介
SIerアーキテクト視点でみたKotlinの紹介SIerアーキテクト視点でみたKotlinの紹介
SIerアーキテクト視点でみたKotlinの紹介
 
あなたとAndroid!?今すぐダウンロード
あなたとAndroid!?今すぐダウンロードあなたとAndroid!?今すぐダウンロード
あなたとAndroid!?今すぐダウンロード
 
Kotlinで関数拡張しちゃうぞ![修正版]
Kotlinで関数拡張しちゃうぞ![修正版]Kotlinで関数拡張しちゃうぞ![修正版]
Kotlinで関数拡張しちゃうぞ![修正版]
 
とある現場のシステムアーキテクチャ
とある現場のシステムアーキテクチャとある現場のシステムアーキテクチャ
とある現場のシステムアーキテクチャ
 
関ジャバの間においでよ!
関ジャバの間においでよ!関ジャバの間においでよ!
関ジャバの間においでよ!
 
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情についてあなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
 
Web API Design for JAX-RS
Web API Design for JAX-RSWeb API Design for JAX-RS
Web API Design for JAX-RS
 
ゆるふわアーキを支える技術
ゆるふわアーキを支える技術ゆるふわアーキを支える技術
ゆるふわアーキを支える技術
 
Nullなのはいけないと思います!
Nullなのはいけないと思います!Nullなのはいけないと思います!
Nullなのはいけないと思います!
 
生きろ!チーム開発! 300人月の仲間はみな死んだ
生きろ!チーム開発! 300人月の仲間はみな死んだ生きろ!チーム開発! 300人月の仲間はみな死んだ
生きろ!チーム開発! 300人月の仲間はみな死んだ
 
Play!30分クッキング
Play!30分クッキングPlay!30分クッキング
Play!30分クッキング
 
システムアーキテクト
システムアーキテクトシステムアーキテクト
システムアーキテクト
 
Xtend30分クッキング やきに駆動
Xtend30分クッキング   やきに駆動Xtend30分クッキング   やきに駆動
Xtend30分クッキング やきに駆動
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数
 
Xtend30分クッキング
Xtend30分クッキングXtend30分クッキング
Xtend30分クッキング
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
鹿駆動
鹿駆動鹿駆動
鹿駆動
 
MyBatisで流れるようなメソッドチェーン
MyBatisで流れるようなメソッドチェーンMyBatisで流れるようなメソッドチェーン
MyBatisで流れるようなメソッドチェーン
 
About Jobs
About JobsAbout Jobs
About Jobs
 
play framework 勉強会 in 関西
play framework 勉強会 in 関西play framework 勉強会 in 関西
play framework 勉強会 in 関西
 

システムアーキテクト~My batis編~