MyBatisの基本概念とJDBCからの移行

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

タグ: MyBatis JDBC ORM SQLマッピング 型ハンドラ

7月11日 16:32 投稿