ORMフレームワークの選択基準
Hibernateなどのフレームワークは全テーブルマッピングを行うため、以下の課題があります:
- SQLのカスタマイズが困難
- 不要なフィールドもSELECTされ、ネットワークとシリアライゼーションのオーバーヘッドが増加
- SQLが隠蔽されるため、パフォーマンスチューニングが不便
Maven依存関係の設定
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
</dependencies>
従来のJDBC実装例
public class JdbcExample {
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/db";
private static final String USERNAME = "root";
private static final String PASSWORD = "password";
public List<User> queryUsers(String name) {
List<User> users = new ArrayList<>();
Connection connection = null;
PreparedStatement statement = null;
try {
Class.forName(DRIVER);
connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
String sql = "SELECT * FROM users WHERE user_name = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, name);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
User user = new User();
user.setRealName(resultSet.getString("real_name"));
user.setSex(resultSet.getByte("sex"));
user.setMobile(resultSet.getString("mobile"));
users.add(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// リソース解放処理
}
return users;
}
}
MyBatisクイックスタート
public class MyBatisExample {
private SqlSessionFactory sessionFactory;
@Before
public void setup() throws IOException {
String config = "mybatis-config.xml";
InputStream stream = Resources.getResourceAsStream(config);
sessionFactory = new SqlSessionFactoryBuilder().build(stream);
}
@Test
public void basicUsage() {
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectById(1);
System.out.println(user);
}
}
MyBatis設定ファイル
<configuration>
<properties resource="database.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="UNPOOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="com.example.mapper.UserMapper"/>
</mappers>
</configuration>
型ハンドラのカスタマイズ
MyBatisではTypeHandlerを実装することで、Java型とデータベース型の変換をカスタマイズできます:
public class CustomTypeHandler extends BaseTypeHandler<CustomType> {
@Override
public void setParameter(PreparedStatement ps, int index,
CustomType parameter, JdbcType jdbcType) {
ps.setString(index, parameter.toString());
}
@Override
public CustomType getResult(ResultSet rs, String columnName) {
return CustomType.fromString(rs.getString(columnName));
}
}