tamuraです。
今回はDropwizardでデータベースを参照していきます。
pom.xml
以下の記述をpom.xmlに追加します。
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-jdbi</artifactId>
<version>${dropwizard.version}</version>
</dependency>
<dependency>
<groupId>com.github.tamurashingo.dbutil3</groupId>
<artifactId>dbutil3</artifactId>
<version>0.1.0</version>
</dependency>
DAOの作成
まずはDAOのinterfaceを作成します。 messageId
を渡すとそれに対応したSaying
を返すDAOを定義します。
package com.github.tamurashingo.dropwizard.helloworld.dao;
import com.github.tamurashingo.dropwizard.helloworld.Saying;
import com.google.common.base.Optional;
public interface MessageDAO {
public Optional<Saying> getMessage(String messageId);
}
続いてMySQL用の実装を作成します。 具体的にSQLを書いていきます。
package com.github.tamurashingo.dropwizard.helloworld.dao.impl;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
import org.skife.jdbi.v2.sqlobject.customizers.SingleValueResult;
import com.github.tamurashingo.dropwizard.helloworld.Saying;
import com.github.tamurashingo.dropwizard.helloworld.dao.MessageDAO;
import com.github.tamurashingo.dropwizard.helloworld.dao.impl.mapper.SayingMapper;
import com.google.common.base.Optional;
public interface MessageDAOMySQLImpl extends MessageDAO {
@Override
@SingleValueResult(Saying.class)
@SqlQuery(
" select "
+ " message "
+ " from "
+ " m_message "
+ " where "
+ " id = :messageId "
)
@Mapper(SayingMapper.class)
public Optional<Saying> getMessage(@Bind("messageId") String messageId);
}
以下の3つのアノテーションでどのようなSQLが実行されてどのような結果を返すかを定義しています。
@SingleValueResult
@SqlQuery
@Mapper
余談ですが、リスト(List<Saying>
)を返したい場合は、@SingleValueResult
のアノテーションを外すだけで大丈夫です。
続いて、SQLの結果をJavaBeanにするマッパーを定義します。 これは拙作のDBUtils3
を(わざわざ)使います。
Mapper
は毎回インスタンスが生成されるようなので、BeanBuilder
はstatic
で持つようにしています。
package com.github.tamurashingo.dropwizard.helloworld.dao.impl.mapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import com.github.tamurashingo.dbutils3.BeanBuilder;
import com.github.tamurashingo.dbutils3.BeanBuilderException;
import com.github.tamurashingo.dropwizard.helloworld.Saying;
public class SayingMapper implements ResultSetMapper<Saying> {
private static final BeanBuilder builder;
static {
builder = new BeanBuilder(Saying.class);
}
@Override
public Saying map(int index, ResultSet r, StatementContext ctx) throws SQLException {
try {
Saying saying = builder.build(r);
return saying;
}
catch (BeanBuilderException ex) {
throw new SQLException(ex);
}
}
}
Resource
Resource
でDAOを使うため、コンストラクタでDAOを受け取るように変更します。
また、messageId
が渡されなかったりデータベースに値がなかったときのために初期値を作っています。
package com.github.tamurashingo.dropwizard.helloworld;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import com.github.tamurashingo.dropwizard.helloworld.dao.MessageDAO;
import com.google.common.base.Optional;
@Path("/hello-world")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
private MessageDAO messageDAO;
private Saying defaultValue = new Saying("hello world");
public HelloWorldResource(MessageDAO messageDAO) {
this.messageDAO = messageDAO;
}
@GET
public Saying sayHello(@QueryParam("messageid") Optional<String> messageId) {
if (messageId.isPresent()) {
return messageDAO.getMessage(messageId.get()).or(defaultValue);
}
else {
return defaultValue;
}
}
}
Saying
もBeanBuilder
を使うにあたり、
@Column
setter
が必要なので変更します。
package com.github.tamurashingo.dropwizard.helloworld;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.tamurashingo.dbutils3.Column;
public class Saying {
@Column("message")
private String greeting;
public Saying() {
}
public Saying(String greeting) {
this.greeting = greeting;
}
@JsonProperty
public String getGreeting() {
return this.greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
Application
最後にApplication
を修正します。 DAOの生成などを追加しています。
package com.github.tamurashingo.dropwizard.helloworld;
import org.skife.jdbi.v2.DBI;
import com.github.tamurashingo.dropwizard.helloworld.dao.MessageDAO;
import com.github.tamurashingo.dropwizard.helloworld.dao.impl.MessageDAOMySQLImpl;
import io.dropwizard.Application;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.jdbi.DBIFactory;
import io.dropwizard.migrations.MigrationsBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class HelloWorldApplication extends Application<HelloWorldConfiguration> {
public static void main(String...args) throws Exception {
new HelloWorldApplication().run(args);
}
@Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
bootstrap.addBundle(new MigrationsBundle<HelloWorldConfiguration>() {
@Override
public DataSourceFactory getDataSourceFactory(HelloWorldConfiguration configuration) {
return configuration.getDataSourceFactory();
}
});
}
@Override
public void run(HelloWorldConfiguration configuration, Environment environment) throws Exception {
final DBIFactory factory = new DBIFactory();
final DBI jdbi = factory.build(environment, configuration.getDataSourceFactory(), "helloworlddb");
final MessageDAO messageDAO = jdbi.onDemand(MessageDAOMySQLImpl.class);
environment.jersey().register(new HelloWorldResource(messageDAO));
}
}
実行
$ mvn clean package
$ java -jar target/helloworld-0.0.1-SNAPSHOT.jar server hello-world.yml
でサーバが実行します。
http://localhost:8080/hello-world
にアクセスすると初期値である
{"greeting":"hello world"}
が表示されます。
http://localhost:8080/hello-world?messageid=00002
にアクセスするとデータベースに格納した値の
{"greeting":"こんにちは"}
が表示されます。