Spring4でDB接続してSQL実行(JDBCTemplate)

ほしがき2017/09/17(日) - 11:32 に投稿

 

Spring Framework4でDB接続&SQL実行を行います。

Springって色々やり方あるし難しいです・・・。

自分なりのやり方を見つけてください。

今までの記事

上記の記事で作成したプロジェクトを使います。

コネクションプールはCommons DBCP2を使用します。

やることは

  • pom.xmlに使うライブラリを追加
  • servlet-context.xml(applicationContext.xml)にDB関連の設定追加
  • ControllerクラスでSQL実行

です。

環境

  • Spring Framework 4.3.11.RELEASE(4.3.10から11にした)
  • Java 8
  • Commons DBCP2
  • PostgreSQL9.6
  • tomcat 9.0
  • eclipse 4.7 Oxygen
  • pom.xmlに使うライブラリを追加

以前、個人的にあるサイトを運営していたのですがDBCPは使いませんでした。

DBコネクションもSpringの機能で作っていなかったし大したアクセス数は見込めない、且つめんどくさいという理由で。

それでもやはりDBCPは使った方がいいです。Springの機能を使うと楽々DBCP使えるので使いましょう。

あの時はどうかしてました。

JDBCは自分の使うDBのものにしてください。

私はPostgreSQL一択です。象さん大好き

pom.xml(抜粋)

        <!-- JDBC -->
        <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>

 

  • servlet-context.xml(applicationContext.xml)にDB関連の設定追加

contextファイルにDBCP、JDBCTemplateの設定を追加します。

JDBCTemplateでSQLを実行できます。

良く仕事ではMyBatis(iBATIS)を使いますが、正直あまり好きではない・・・。

ついでにトランザクション(TransactionManager)の管理も任せてしまいます。

追加するのは<!-- DB関連 -->のコメントの下です。

以下の項目に関しては自分の環境に合わせて変更してください。

  • driverClassName
  • url
  • username
  • password

servlet-context.xml(applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />

    <mvc:resources mapping="/**" location="/resthtml/" />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="spring.rest.test" />

    <!-- DB関連 -->
    <beans:bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <beans:property name="driverClassName" value="org.postgresql.Driver"/>
        <beans:property name="url" value="jdbc:postgresql://localhost:5433/testdb"/>
        <beans:property name="username" value="postgres"/>
        <beans:property name="password" value="postgres"/>
        <beans:property name="defaultAutoCommit" value="false" />
        <beans:property name="initialSize" value="10"/>
        <beans:property name="maxTotal" value="30"/>
        <beans:property name="minIdle" value="10"/>
        <beans:property name="maxWaitMillis" value="600000"/>
        <beans:property name="validationQuery" value="select 1"/>
    </beans:bean>

    <tx:annotation-driven transaction-manager="transactionManager" />
    <beans:bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <beans:property name="dataSource" ref="dataSource" />
    </beans:bean>

    <beans:bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <beans:property name="dataSource" ref="dataSource" />
    </beans:bean>

</beans:beans>

ちょっとメモ。これが出るときは<property name="xxxx">ではなく<beans:property name="xxx">とする。

Bean definitions can have zero or more properties. Property elements correspond to JavaBean setter 
 methods exposed by the bean classes. Spring supports primitives, references to other beans in the same 
 or related factories, lists, maps and properties.

 

  • ControllerクラスでSQL実行

Controllerクラスは新規で作成します。

@Transactionalがついているとメソッド開始時点でトランザクションを開始し、終了するとコミットされます。

例外発生時はRuntimeExceptionでロールバック、Exceptionでコミットとなるみたいなのですが大体コミットしてほしくない場合が多いと思います。

その場合は(rollbackFor = Exception.class)を記述するとException発生時でもロールバックしてくれます。

以下のソースでは2レコード挿入していますが、両方ともメソッド終了時にコミットされます。

なお、コンテキストから取得したJDBCTemplateのオブジェクト(tmp)と変数のtemplateは同一のオブジェクトです。

 

JDBCTemplateSample.java

package spring.rest.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JDBCTemplateSample {

    @Autowired
    ApplicationContext context;

    @Autowired
    private JdbcTemplate template;

    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value="/jdbc_template", method = RequestMethod.GET)
    public void jdbcTemplate() throws Exception {

        try {
            template.update("insert into testtable values(1, 'no1')");

            JdbcTemplate tmp = (JdbcTemplate)context.getBean("jdbcTemplate");
            tmp.update("insert into testtable values(2, 'no2')");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

とりあえずこれでSQLの実行ができました。

ちょっと気になることがありますが。

advised by org.springframework.transaction.interceptor.TransactionInterceptor.invoke(org.aopalliance.intercept.MethodInvocation)

Eclipseでメソッド宣言箇所でこのメッセージが出てくる。

なんだろうこれ?

エラーではなさそうな気がするので一旦放置。