kazpgmの日記

『プログラム自動作成@自動生成』作成の日記

javaのSpringとMybatisについて調査した。(今年はPHPじゃないのをはじめた)

javaのSpringとMybatisについて調査した
 1.mybatis-jpetstore-6.0.1-bundle.zip(http://code.google.com/p/mybatis/downloads/list?q=Product=Sample)のソースを流用(これ自体はWEBシステムのサンプルなので)してJAVAバッチを作った。
 2.今回は動的SQLを使わなかったがここ(http://www.mybatis.org/core/ja/dynamic-sql.html)を参考にしてあとで試す。
 3.pom.xmlを作るのにここ(http://brightgenerous.blogspot.jp/2012/01/spring3-mybatis3.html)を見本にした。
eclipseMavenのプロジェクトにした

■App.java(JAVAバッチ)のサンプル

package org.mybatis.jpetstore.app;
import java.util.List;

import org.mybatis.jpetstore.domain.Category;
import org.mybatis.jpetstore.domain.Signon2;
import org.mybatis.jpetstore.service.CatalogService;
import org.mybatis.jpetstore.service.Signon2Service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    private static ApplicationContext context;

    /**
     * @param args
     */
    public static void main(String[] args) {

        System.out.println("start");
        context = new ClassPathXmlApplicationContext("applicationContext.xml");
        CatalogService catalogService = context.getBean(CatalogService.class);
        Category category = catalogService.getCategory("FISH");
        System.out.println("category=" + category.toString());
        List<Category> list = catalogService.getCategoryList();
        System.out.println("list=" + list);

        System.out.println("------");
        Signon2Service sigon2Service = context.getBean(Signon2Service.class);
        Signon2 signon2 = sigon2Service.getSignon2("ACID");
        System.out.println("sigon2=" + signon2.toString());
         signon2 = sigon2Service.getSignon2("ACID","ACID");
        System.out.println("sigon2=" + signon2.toString());

        System.out.println("------");
        Signon2 signon2a = new Signon2();
        signon2a.setUserName("ACID");
        signon2a.setPassWord("ACID");
        signon2 = sigon2Service.getSignon2(signon2a);
        System.out.println("sigon2=" + signon2.toString());
         signon2 = sigon2Service.getSignon2("ACID","ACID");
        //System.out.println("sigon2=" + signon2.toString());

//        System.out.println("------");
//        signon2a = new Signon2();
//        signon2a.setUserName("XXXX");
//        signon2a.setPassWord("YYYY");
//        sigon2Service.insertSignon2(signon2a);
//        signon2 = sigon2Service.getSignon2(signon2a);
//        System.out.println("sigon2b=" + signon2.toString());

        System.out.println("==before doAll========================");
        try {
            sigon2Service.doAll();
        } catch (Exception up) {
            System.out.println("------");
            System.out.println("---Exception---");
            System.out.println("Exception==" + up.toString());
        }
        System.out.println("==after doAll========================");

        System.out.println("////////");
        signon2a = new Signon2();
        signon2a.setUserName("ACID");
        signon2a.setPassWord("ACID");
        Signon2 signon2b = sigon2Service.getSignon2(signon2a);
        if (signon2b != null) {
            System.out.println("sigon2b=" + signon2b.toString());
        } else {
            System.out.println("------");
            System.out.println("---sigon2b null---");
        }
    }
}

■applicationContext.xml ←Springを使う為の基本となる構成ファイル

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Copyright 2010 The myBatis Team

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xmlns:jdbc="http://www.springframework.org/schema/jdbc"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

   <!-- in-memory database and a datasource -->
    <jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:database/jpetstore-hsqldb-schema.sql"/>
        <jdbc:script location="classpath:database/jpetstore-hsqldb-dataload.sql"/>
    </jdbc:embedded-database>

    <!-- transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- enable component scanning and autowire (beware that this does not enable mapper scanning!) -->
    <context:component-scan base-package="org.mybatis.jpetstore.service" />

    <!-- enable transaction demarcation with annotations -->
    <tx:annotation-driven />

    <!-- define the SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="typeAliasesPackage" value="org.mybatis.jpetstore.domain" />
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!-- scan for mappers and let them be autowired -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.mybatis.jpetstore.persistence" />
    </bean>
</beans>

log4j.properties ←これは関係ないが自分用に載せておく。・・・よくわかっていないので

# Rules reminder:
# DEBUG < INFO < WARN < ERROR < FATAL

# Global logging configuration
log4j.rootLogger=WARN, stdout

# My logging configuration...
log4j.logger.org.mybatis.jpetstore=TRACE

## Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n

■mybatis-config.xml ←テーブル項目とEntityBean(変数名は項目名をキャメルにしたものになっている)のマッピングを自動でやってもらう。applicationContext.xmlのSqlSessionFactoryのconfigLocationに設定している。

<?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>
<settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

■pom.xml ←Mavenのプロジェクト用。これで動いたというレベルなので、これが100%正解とは言えない

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>xxxx</groupId>
    <artifactId>sample</artifactId>
    <packaging>jar</packaging>
    <version>6.0.2-SNAPSHOT</version>
    <name>sample</name>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.1.1</version>
        </dependency>
<!--
    Core utilities used by other modules.
    Define this if you use Spring Utility APIs
    (org.springframework.core.*/org.springframework.util.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Expression Language (depends on spring-core)
    Define this if you use Spring Expression APIs (org.springframework.expression.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-expression</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Bean Factory and JavaBeans utilities (depends on spring-core)
    Define this if you use Spring Bean APIs (org.springframework.beans.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Aspect Oriented Programming (AOP) Framework (depends on spring-core, spring-beans)
    Define this if you use Spring AOP APIs (org.springframework.aop.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Application Context (depends on spring-core, spring-expression, spring-aop, spring-beans)
    This is the central artifact for Spring's Dependency Injection Container and is generally
      always defined
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Various Application Context utilities, including EhCache, JavaMail, Quartz, and
      Freemarker integration
    Define this if you need any of these integrations
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Transaction Management Abstraction (depends on spring-core, spring-beans, spring-aop,
      spring-context)
    Define this if you use Spring Transactions or DAO Exception Hierarchy
      (org.springframework.transaction.*/org.springframework.dao.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    JDBC Data Access Library (depends on spring-core, spring-beans, spring-context, spring-tx)
    Define this if you use Spring's JdbcTemplate API (org.springframework.jdbc.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Object-to-Relation-Mapping (ORM) integration with Hibernate, JPA, and iBatis.
    (depends on spring-core, spring-beans, spring-context, spring-tx)
    Define this if you need ORM (org.springframework.orm.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Object-to-XML Mapping (OXM) abstraction and integration with JAXB, JiBX, Castor, XStream,
      and XML Beans. (depends on spring-core, spring-beans, spring-context)
    Define this if you need OXM (org.springframework.oxm.*)
-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-oxm</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>

<!--
    Web application development utilities applicable to both Servlet and Portlet Environments
    (depends on spring-core, spring-beans, spring-context)
    Define this if you use Spring MVC, or wish to use Struts, JSF, or another web framework
      with Spring (org.springframework.web.*)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>
-->
<!--
    Spring MVC for Servlet Environments (depends on spring-core, spring-beans, spring-context,
      spring-web)
    Define this if you use Spring MVC with a Servlet Container such as Apache Tomcat
      (org.springframework.web.servlet.*)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>
-->
<!--
    Spring MVC for Portlet Environments (depends on spring-core, spring-beans, spring-context,
      spring-web)
    Define this if you use Spring MVC with a Portlet Container
      (org.springframework.web.portlet.*)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc-portlet</artifactId>
  <version>3.1.0.RELEASE</version>
</dependency>
-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>2.2.8</version>
        </dependency>
    </dependencies>
</project>

■Signon2.java ←EntityBeanのサンプル

package org.mybatis.jpetstore.domain;

import java.io.Serializable;

public class Signon2  implements Serializable {

      private static final long serialVersionUID = 8751282105532159742L;

      private String userName;
      private String passWord;

      public String getUserName() {
        return userName;
      }

      public void setUserName(String userName) {
        this.userName = userName;
      }

      public String getPassWord() {
        return passWord;
      }

      public void setPassWord(String passWord) {
        this.passWord = passWord;
      }
      public String toString() {
        return getUserName() + "," +
                getPassWord()  ;
      }

}

■Signon2Dao.java ←Daoのサンプル。MapperなのだけどDaoという名前のほうが一般的なのでSignon2Dao.javaにした。「getSignon2ByUsername(String userName);」は直接@Selectアノテーションを使ってみた。

package org.mybatis.jpetstore.persistence;

import org.apache.ibatis.annotations.Select;
import org.mybatis.jpetstore.domain.Signon2;

public interface Signon2Dao {

    @Select("SELECT USER_NAME, " +
            "PASS_WORD FROM SIGNON2 " +
            "WHERE USER_NAME = #{userName}")
    Signon2 getSignon2ByUsername(String userName);

    Signon2 getSignon2ByUsernameAndPassword(String userName, String passWord);

    Signon2 getSignon2ByUsernameAndPassword2(Signon2 signon2);

    void insertSignon2(Signon2 signon2);

    void updateSignon2(Signon2 signon2);
}

■Signon2Dao.xml ←Daoのサンプル。Mapper.xmlなのだけどDaoという名前のほうが一般的なのでSignon2Dao.xmlにした。

<?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="org.mybatis.jpetstore.persistence.Signon2Dao">

  <cache />

  <select id="getSignon2ByUsernameAndPassword" parameterType="Signon2" resultType="Signon2">
     SELECT
          USER_NAME,
          PASS_WORD
    FROM SIGNON2
    WHERE USER_NAME = #{param1}
       AND PASS_WORD = #{param2}
   </select>

  <select id="getSignon2ByUsernameAndPassword2" parameterType="Signon2" resultType="Signon2">
     SELECT
          USER_NAME,
          PASS_WORD
    FROM SIGNON2
    WHERE USER_NAME = #{userName}
       AND PASS_WORD = #{passWord}
   </select>

  <update id="updateSignon2" parameterType="Signon2">
    UPDATE SIGNON2 SET PASS_WORD = #{passWord}
    WHERE USER_NAME = #{userName}
  </update>

  <insert id="insertSignon2" parameterType="Signon2">
    INSERT INTO SIGNON2 (USER_NAME,PASS_WORD)
    VALUES (#{userName}, #{passWord})
  </insert>

</mapper>

■Signon2Service.javaトランザクションの動きをテストするため、わざと重複エラーを起こしているよ。

package org.mybatis.jpetstore.service;

import org.apache.log4j.Logger;
import org.mybatis.jpetstore.domain.Signon2;
import org.mybatis.jpetstore.persistence.Signon2Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class Signon2Service {
       private static Logger log=Logger.getLogger(Signon2Service.class.getName());

      @Autowired
      private Signon2Dao signon2Dao;

      public Signon2 getSignon2(String username) {
        return signon2Dao.getSignon2ByUsername(username);
      }

      public Signon2 getSignon2(String username, String password) {
        return signon2Dao.getSignon2ByUsernameAndPassword(username, password);
      }

      public Signon2 getSignon2(Signon2 signon2) {
        return signon2Dao.getSignon2ByUsernameAndPassword2(signon2);
      }

      public void insertSignon2(Signon2 signon2) {
        signon2Dao.insertSignon2(signon2);
      }

      public void updateSignon2(Signon2 signon2) {
        signon2Dao.updateSignon2(signon2);
      }

      @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
      public void doAll() {
//            try {
             log.debug("-- log log log start");
              System.out.println("start");
            System.out.println("------");
            Signon2 signon2b = getSignon2("ACID");
            System.out.println("sigon2b=" + signon2b.toString());
            signon2b = getSignon2("ACID","ACID");
            System.out.println("sigon2b=" + signon2b.toString());

            System.out.println("------");
            Signon2 signon2a = new Signon2();
            signon2a.setUserName("ACID");
            signon2a.setPassWord("ACID");
            signon2b = getSignon2(signon2a);
            System.out.println("sigon2=" + signon2b.toString());
             signon2b = getSignon2("ACID","ACID");
            System.out.println("sigon2=" + signon2b.toString());

            System.out.println("------");
            signon2a = new Signon2();
            signon2a.setUserName("XXXX");
            signon2a.setPassWord("YYYY");
            insertSignon2(signon2a);
            insertSignon2(signon2a); // テストのためここで重複エラーを起こす!
            signon2b = getSignon2(signon2a);
            System.out.println("sigon2b=" + signon2b.toString());
            signon2a.setPassWord("ZZZZ");
            updateSignon2(signon2a);
            signon2b = getSignon2(signon2a);
            System.out.println("sigon2=" + signon2b.toString());
// ここでキャッチしないで、呼び元でキャッチするほうがいい。(だからコメントアウトした)
// doAllを抜けるとき@Transactionalの
// rollbackFor=Exception.classによりロールバックされている。例外は帰ってくるので呼び元で処理する。
// ・・・呼び元でtry、catch処理しないと、例外発生で落ちてしまうので注意。
//         } catch (Exception up) {
//            //log the error
//             log.warn("エラー:" + up);
//             System.out.println("------");
//            System.out.println("---Exception---");
//            System.out.println("Exception==" + up.toString());
//            throw up;
//         }
      }
}