SAStrutsを勉強してみる (3) - S2JDBCを使う -
タイトル通り。S2JDBCを使ってMySQLデータベースに接続してテーブルにアクセスしてみる
pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>toplink-essentials</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.1_spec</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId>
<version>1.0</version>
</dependency>
src/main/resources/s2jdbc.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd">
<components>
<include path="jdbc.dicon"/>
<include path="s2jdbc-internal.dicon" />
<component name="jdbcManager" class="org.seasar.extension.jdbc.manager.JdbcManagerImpl">
<property name="maxRows">0</property>
<property name="fetchSize">0</property>
<property name="queryTimeout">0</property>
<property name="dialect">mysqlDialect</property>
</component>
</components>
dialectはMySQL以外とかだとそれに応じた値を設定する。んでJDBC接続な情報はjdbc.diconに設定する
src/main/resources/jdbc.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN" "http://www.seasar.org/dtd/components21.dtd">
<components namespace="jdbc">
<include path="jta.dicon"/>
<component name="xaDataSource" class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
<property name="driverClassName">"com.mysql.jdbc.Driver"</property>
<property name="URL">"jdbc:mysql://localhost:3306/sample"</property>
<property name="user">"username"</property>
<property name="password">"password"</property>
</component>
<component name="connectionPool"
class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
<property name="timeout">600</property>
<property name="maxPoolSize">10</property>
<property name="allowLocalTx">true</property>
<destroyMethod name="close"/>
</component>
<component name="DataSource"
class="org.seasar.extension.dbcp.impl.DataSourceImpl"
/>
</components>
んまぁxaDataSourceな所をいじれば良いみたい。でMySQLで
CREATE TABLE sample(
id int auto_increment primary key,
data varchar(255) NOT NULL UNIQUE,
created_at datetime NOT NULL
) ENGINE=InnoDB
とかをデータベースにテーブルを作っておく。あとはクラス群を作る
sample.entity.Sample
package sample.entity;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@Table(name = "sample")
public class Sample {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int id;
@Column(name = "data", nullable = false, unique = true)
public String data;
@Column(name = "created_at", nullable = false, unique = false)
@Temporal(TemporalType.DATE)
public Date date;
@Override
public String toString() {
return String.format("[%s]: %s", id, data);
}
}
publicにしたくなければ普通にgetter/setterを書けば良いみたい
sample.service.SampleService
まぁService系を使ってデータベースとの手続きに関する処理を定義すれば良いのかも
package sample.service;
import java.util.List;
import javax.annotation.Resource;
import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.extension.jdbc.OrderByItem;
import org.seasar.extension.jdbc.OrderByItem.OrderingSpec;
import org.seasar.extension.jdbc.exception.SEntityExistsException;
import org.seasar.extension.jdbc.where.SimpleWhere;
import org.seasar.framework.exception.SQLRuntimeException;
import sample.entity.Sample;
public class SampleService {
@Resource
private JdbcManager jdbcManager;
public List<Sample> getSamples() {
OrderByItem order = new OrderByItem("id", OrderingSpec.DESC);
return jdbcManager.from(Sample.class).orderBy(order).getResultList();
}
public List<Sample> getSamples(String[] ids) {
SimpleWhere where = new SimpleWhere();
where.in("id", (Object[])ids);
return jdbcManager.from(Sample.class).where(where).getResultList();
}
public Sample getSampleById(int id) {
return jdbcManager.from(Sample.class).where("id = ?", id).getSingleResult();
}
public Sample createSample(Sample sample) {
Sample createdSample = null;
try {
int rowUpdate = jdbcManager.insert(sample).execute();
if (rowUpdate > 0) {
createdSample = sample;
}
} catch (SEntityExistsException e) {
e.printStackTrace();
} catch (SQLRuntimeException e) {
e.printStackTrace();
}
return createdSample;
}
public boolean deleteSamples(List<Sample> samples) {
boolean deleteSuccessfulFlag = false;
try {
if (jdbcManager.deleteBatch(samples).execute().length > 0) {
deleteSuccessfulFlag = true;
}
} catch (SQLRuntimeException e) {
e.printStackTrace();
}
return deleteSuccessfulFlag;
}
}
sample.form.Sample2Form
package sample.form;
import org.seasar.struts.annotation.IntegerType;
import org.seasar.struts.annotation.Required;
public class Sample2Form {
@Required(target = "show")
@IntegerType
public String id;
@Required(target = "add")
public String data;
@Required(target = "delete")
public String[] checkId;
}
sample.action.Sample2Action
package sample.action;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import org.seasar.framework.beans.util.Beans;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;
import org.seasar.struts.enums.SaveType;
import org.seasar.struts.util.ResponseUtil;
import sample.entity.Sample;
import sample.form.Sample2Form;
import sample.service.SampleService;
public class Sample2Action {
@Resource
private HttpServletResponse response;
@ActionForm
@Resource
protected Sample2Form sample2Form;
@Resource
private SampleService sampleService;
public List<Sample> samples;
@Execute(validator = false, removeActionForm = true)
public String index() {
samples = sampleService.getSamples();
return "index.jsp";
}
@Execute(input = "?redirect=true", saveErrors = SaveType.SESSION, redirect = true)
public String add() {
Sample sample = Beans.createAndCopy(Sample.class, sample2Form).execute();
sample.date = new Date();
sampleService.createSample(sample);
return new String();
}
@Execute(validator = false, urlPattern = "show/{id}")
public String show() {
Sample sample = sampleService.getSampleById(Integer.parseInt(sample2Form.id));
if (sample != null) {
ResponseUtil.write(sample.toString(), "text/plain");
} else {
try {
response.sendError(404);
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Execute(input = "?redirect=true", saveErrors = SaveType.SESSION, redirect = true)
public String delete() {
List<Sample> samples = sampleService.getSamples(sample2Form.checkId);
sampleService.deleteSamples(samples);
return new String();
}
}
src/main/webapp/WEB-INF/views/sample2/index.jsp
<html>
<body>
<html:errors />
<s:form>
<html:text property="data" />
<input type="submit" name="add" value="追加" />
</s:form>
<s:form>
<c:forEach var="sample" items="${samples}">
<div>
<html:checkbox property="checkId" value="${sample.id}" />
<s:link href="show/${sample.id}"><c:out value="${sample.data}" /></s:link>
</div>
</c:forEach>
<input type="submit" name="delete" value="削除" />
</s:form>
</body>
</html>
てな感じかと。
追記
Entityなサービスに関してはS2AbstractServiceを継承して使うのを推奨しているらしい。なので自前でServiceクラスな所でJdbcServiceを注入させるようなのは必要ない模様