MyBatis-Springを試してみました。

MyBatis単独の場合と違ってSpring側でコネクションを管理してくれるので、直接SqlSessionを使って管理する必要がありません。

アプリケーション開発者側では、SpringがインジェクションしてくれたMapperインターフェースを通してDB操作を行うだけで完結できます。

トランザクションはMyBatisに限らずですが、@Transactionalアノテーションメソッドに付与することで、Spring側で管理してくれます。

参考

サンプルコード

勉強メモとして作ったサンプルコード。

https://github.com/momotaro-lucy/mybatis_spring_sample

公式サイト

Spring連携版についてもMyBatisと同様に公式サイトが用意されています。 http://mybatis.github.io/spring/ja/getting-started.html

メモ

セットアップ

開発するMavenプロジェクトに、MyBatis-Springへの依存関係を付与します。

<dependency>
 <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.2.3</version>
</dependency>

MyBatis-SpringはもちろんMyBatisやSpringフレームワーク自体に依存関係を持っていますが、Maven上の指定がprovidedとなっているため、 Eclipse経由などでJavaアプリケーションとしてそのまま実行する場合は、MyBatisやSpringフレームワーク自体にも依存関係を付与する必要があります。

<dependency>
 <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.2.3</version>
</dependency>
<!-- MyBatis -->
<dependency>
 <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.3.0</version>
</dependency>
<!-- Spring -->
<dependency>
 <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>3.2.13.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>3.2.13.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.springframework.batch</groupId>
  <artifactId>spring-batch-infrastructure</artifactId>
  <version>3.0.4.RELEASE</version>
</dependency>

メモ

ApplicationContext.xmlを作成します。

Springの設定ファイル ApplicationContext.xmlにデータソース・SqlSessionFactory・Mapperの設定を記述します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- データソースの設定 -->
   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="org.postgresql.Driver"/>
      <property name="url" value="jdbc:postgresql://localhost:5432/mybatis_spring_sample" />
      <property name="username" value="mybatis_sample_user" />
      <property name="password" value="mybatis_sample_password" />
   </bean>

    <!-- SqlSessionFactoryの設定 -->
   <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
      <property name="dataSource" ref="dataSource"/>
   </bean>
   
   <!-- Mapperインターフェースの登録 -->
   <bean id="SampleMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
      <property name="mapperInterface" value="jp.momotaro_lucy.sample.mybatis_spring.mapper.SampleMapper" />
      <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>

    <context:annotation-config />
    <context:component-scan base-package="jp.momotaro_lucy.sample.mybatis_spring" />
</beans>

Mapperインターフェースが複数存在する場合は、パッケージ単位での指定も可能です。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
    <!-- データソースの設定 -->
   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="org.postgresql.Driver"/>
      <property name="url" value="jdbc:postgresql://localhost:5432/mybatis_spring_sample" />
      <property name="username" value="imart" />
      <property name="password" value="imart" />
   </bean>

    <!-- SqlSessionFactoryの設定 -->
   <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
      <property name="dataSource" ref="dataSource"/>
   </bean>
   
   <!-- Mapperインターフェースが配置されたパッケージの設定 -->
   <mybatis:scan base-package="jp.momotaro_lucy.sample.mybatis_spring.mapper" />

    <context:annotation-config />
    <context:component-scan base-package="jp.momotaro_lucy.sample.mybatis_spring" />
</beans>

Mapperインターフェースを作成します。

ApplicationContext.xmlで指定したMapperクラスを作成します。

https://mybatis.github.io/spring/ja/mappers.html

public interface SampleMapper {
  
  @Insert("insert into mybatis_sample_table (item_cd, item_name, item_comment) values(#{itemCd}, #{itemName}, #{itemComment})")
  public void insert(SampleModel model);

  @Select("select item_cd as itemCd, item_name as itemName, item_comment as itemComment from mybatis_sample_table where item_cd = #{itemCd}")
  public SampleModel select(String itemCd);
  
  @Update("update mybatis_sample_table set item_name = #{itemName}, item_comment = #{itemComment} where item_cd = #{itemCd}")
  public void update(SampleModel model);
}

ORマッパーの呼び出し側の実装を作成します。

SpringがインジェクションしたMapperインターフェースを操作するだけでSQLが実行されます。 @Transactionalのアテーションをメソッドに付与することで、実行中のトランザクションがない場合はSpringフレームワーク側で勝手にトランザクションを張ってくれます。

https://mybatis.github.io/spring/ja/transactions.html

@Service
public class SampleExecuter {
  
  @Autowired
  SampleMapper mapper;
  
  public static void main(String args[]){
    ConfigurableApplicationContext appContext = new FileSystemXmlApplicationContext("src/main/resources/applicationContext.xml");
    SampleExecuter executer = appContext.getBean(SampleExecuter.class);
    executer.execute();
    appContext.close();
  }
  
  @Transactional
  public void execute(){
    // 登録
    SampleModel model = new SampleModel();
    model.setItemCd(UUID.randomUUID().toString());
    model.setItemName(UUID.randomUUID().toString());
    model.setItemComment(UUID.randomUUID().toString());
    mapper.insert(model);
    System.out.println("Insert Data");
    System.out.println("itemCd : " + model.getItemCd());
    System.out.println("itemName : " + model.getItemName());
    System.out.println("itemComment : " + model.getItemComment());
    System.out.println("");
    
    // 更新
    model.setItemName(UUID.randomUUID().toString());
    model.setItemComment(UUID.randomUUID().toString());
    mapper.update(model);
    System.out.println("Update Data");
    System.out.println("itemCd : " + model.getItemCd());
    System.out.println("itemName : " + model.getItemName());
    System.out.println("itemComment : " + model.getItemComment());
    System.out.println("");
    
    SampleModel result2 = mapper.select(model.getItemCd());
    System.out.println("Select Data2");
    System.out.println("itemCd : " + result2.getItemCd());
    System.out.println("itemName : " + result2.getItemName());
    System.out.println("itemComment : " + result2.getItemComment());
  }

}