Springに必要なjarについてはSpringの導入&サンプルプログラムを参照。(SpringJDBCのコアとなるのはspring-jdbc-4.2.4.RELEASE.jar)
ここでは扱わないがトランザクションを使用する場合、下記のjarも必要(SpringJDBCでトランザクションを扱う方法を参照)。
テスト用に使用するDB(sampledb)を用意する。DBにはsampletblテーブルが存在し、2件データが入っている状態。
mysql> select * from sampletbl;
+------+-------+
| id | name |
+------+-------+
| 1 | Bill |
| 2 | Kelly |
+------+-------+
2 rows in set (0.00 sec)
mysql>
Springの設定ファイルを作成する。
下記のファイル(ApplicationContext.xml)を作成し、クラスパス直下に配置する。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<-- ①データソースの定義 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/sampledb" />
<property name="username" value="testuser" />
<property name="password" value="testpassword" />
</bean>
<-- ②JdbcTemplateクラス -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<-- ③DAOクラス -->
<bean class="test.SampleDao">
<property name="JdbcTemplate" ref="jdbcTemplate" />
</bean>
</beans>
[説明]
①データソースの定義
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/sampledb" />
<property name="username" value="testuser" />
<property name="password" value="testpassword" />
</bean>
DriverManagerを使用する場合、下記を指定する。
メソッド名 | 戻り値型 |
---|---|
driverClassName | JDBCドライバのクラス名 |
url | データベース接続URL |
username | データベース接続ユーザID |
password | データベース接続パスワード |
②JdbcTemplateクラス
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
DAOで検索や更新をする場合、JdbcTemplateクラス経由で実行するため、ここでbean定義しておく。
さらにJdbcTemplateの生成にはデータソースが必要なため、bean定義のconstructor-argタグのref属性に①のデータソース(dataSource)を参照させている。
③DAOクラス
<bean class="test.SampleDao">
<property name="JdbcTemplate" ref="jdbcTemplate" />
</bean>
次項で作成するSampleDaoクラスの定義。JdbcTemplateを使用するため、propertyタグのref属性で②のJdbcTemplateを参照させている。
ApplicationContext.xmlの定義を図で表すと以下のような参照関係になる。DAOがJdbcTemplateのインスタンスを持ち、JdbcTemplateがDataSourceのインスタンスを持つ。
まずDBに対して検索処理を行うDAOクラス(SampleDao.java)を作成する。
package test;
import java.util.List;
import org.springframework.jdbc.core.JdbcTemplate;
public class SampleDao {
// ①JdbcTemplateの変数宣言
private JdbcTemplate jdbcTemplate;
// ②JdbcTemplateのsetter
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
// ③検索処理
public List select(){
List ret = jdbcTemplate.queryForList("select name from sampletbl", String.class);
return ret;
}
}
[説明]
①JdbcTemplateの変数宣言
private JdbcTemplate jdbcTemplate;
JdbcTemplateを保持する変数。②のメソッドを用意することで、インスタンスが設定される。
②JdbcTemplateのsetter
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
Springがこのメソッドを使用してJdbcTemplateのインスタンスをセットしてくれる。setterはpublicとし、メソッド名は「"set" + bean定義のpropertyタグ#name属性(下記参照)」とする。
<bean class="test.SampleDao">
<property name="JdbcTemplate" ref="jdbcTemplate"></property>
</bean>
③検索処理
public List select(){
List ret = jdbcTemplate.queryForList("select name from sampletbl", String.class);
return ret;
}
JdbcTemplateのqueryXXXメソッド(数多くのメソッドあり)を使用する。
次に上記で作成したDAOを実行するクラス(SpringSample.java)を作成する。
package test;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringSample {
public static void main(String[] args){
// ①コンテキスト取得
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
// ②インスタンスの取得
SampleDao dao = context.getBean(SampleDao.class);
// ③DAOメソッド実行
List names = dao.select();
// ④検索結果を出力
System.out.println(names);
}
}
[説明]
①コンテキスト取得。
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
②インスタンスの取得
SampleDao dao = context.getBean(SampleDao.class);
SampleDaoクラスのインスタンスを取得する。自分で生成せずにgetBeanメソッドを使ってApplicationContextから取得している。
③DAOメソッド実行&④検索結果を出力
List names = dao.select();
System.out.println(names);
任意で作成したSampleDaoの検索メソッドを呼び出し、検索結果をSystem.outで出力する。以下のとおり、DBから値が取得できているのがわかる。
[Bill, Kelly]
前述のSampleDaoはJdbcTemplateをインスタンス変数として保持していたが、DAOにJdbcDaoSupportを継承させるともっとコードがシンプルになる。
JdbcTemplateの定義は不要となり、SampleDaoに直接データソースを参照させる。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<-- ①データソースの定義 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/sampledb" />
<property name="username" value="testuser" />
<property name="password" value="testpassword" />
</bean>
<-- ②DAOクラス -->
<bean class="test.SampleDao">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
JdbcDaoSupportを継承させるとgetJdbcTemplate()でJdbcTemplateが取得できる。またJdbcDaoSupportがsetDataSourceを実装しているため、DAO側で特にdataSourceを受け取るための記述は不要。
package test;
import java.util.List;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
// ①JdbcDaoSupportを継承
public class SampleDao extends JdbcDaoSupport {
// ②検索処理
public List select(){
List ret = getJdbcTemplate().queryForList("select name from sampletbl", String.class);
return ret;
}
}
アノテーションを使う場合、以下のように修正する。
component-scanを使う。これにより、SampleDaoのbean定義が不要となる。DAOがJdbcDaoSupportを継承している場合は、「③JdbcTemplateの定義」も不要。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<-- ①component-scanの定義 -->
<context:component-scan base-package="test" />
<-- ②データソースの定義 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/sampledb" />
<property name="username" value="testuser" />
<property name="password" value="testpassword" />
</bean>
<-- ③JdbcTemplateの定義 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
</beans>
クラスに@Repositoryアノテーションを付け、setJdbcTemplateメソッドに@Autowiredアノテーションを付ける。
@RepositoryによってSpringが自動でインジェクションしてくれるためDAOのbean定義が不要になり、@AutowiredによってJdbcTemplateのインスタンスがセットされる。
package test;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class SampleDao {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
public List select(){
List ret = jdbcTemplate.queryForList("select name from sampletbl", String.class);
return ret;
}
}
実は@Autowiredは変数にも付けられる。変数に付ければsetJdbcTemplateメソッドは不要となる。こちらの方がよりシンプル。
@Autowired
private JdbcTemplate jdbcTemplate;
[補足]
DAOがJdbcDaoSupportを継承している場合は、データソース(dataSource)を受け取るためのメソッドが必要。
setDataSource(DataSource dataSource)を実装したいところだが、JdbcDaoSupportがfinalで@Autowired無しのsetDataSourceメソッドを実装してしまっているため、名前を変えて(今回の場合initとした)@Autowiredを付けておく。受け取ったDataSourceは親クラス(JdbcDaoSupport)のsetDataSourceに渡してやる。
package test;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
@Repository
public class SampleDao extends JdbcDaoSupport {
@Autowired
public void init(DataSource dataSource){
setDataSource(dataSource);
}
public List select(){
List ret = getJdbcTemplate().queryForList("select name from sampletbl", String.class);
return ret;
}
}
下記方法でも可能。変数dataSourceでデータソースを受け取り、コンストラクタ実行後に呼ばれる@PostConstructアノテーションを使って、親メソッドのsetDataSourceにセットしてあげる。
@Autowired
private DataSource dataSource;
@PostConstruct
void init(){
setDataSource(dataSource);
}