|
このExampleは前提条件として以下のテーブル、Bean、dao.diconを使用します。
テーブル:CD
カラム名 |
論理名 |
型 |
NotNull |
主キー |
ID |
ID |
INTEGER |
〇 |
〇 |
TITLE |
アルバム名 |
VARCHAR(100) |
|
|
CONTENT |
内容(ジャンル) |
VARCHAR(200) |
|
|
CDテーブルに関連付くBeanは次の通りです。
<?php
class CdBean {
const TABLE = "CD";
private $id;
private $title;
private $content;
public function getContent() {
return $this->content;
}
public function setContent($content) {
$this->content = $content;
}
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
}
}
?>
各Exampleでincludeしているdiconは以下の通りです。
src/s2dao.php5/dao.dicon
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components namespace="dao">
<include path="%PDO_DICON%" />
<component class="S2Dao_BasicResultSetFactory" />
<component class="S2Dao_BasicStatementFactory" />
<component class="S2Dao_FieldAnnotationReaderFactory" />
<component class="S2Dao_DaoMetaDataFactoryImpl" />
<component name="interceptor" class="S2DaoInterceptor" />
</components>
src/example/pdo.dicon
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"components21.dtd">
<components namespace="pdo">
<component name="dataSource" class="S2Container_PDODataSource">
<property name="dsn">"mysql:host=localhost; dbname=s2con"</property>
<property name="user">"root"</property>
<property name="password">"pass"</property>
</component>
</components>
また、テーブルの状態は以下の通りです。
mysql> select * from CD order by ID;
+----+--------------------+---------+
| ID | TITLE | CONTENT |
+----+--------------------+---------+
| 1 | HeyJude | Rock |
| 2 | ride on technology | |
| 3 | あの木何の木 | J-POP |
| 20 | gonna rice | NULL |
+----+--------------------+---------+
S2Dao.PHP5を用いる場合の簡単なサンプルです。
作成するファイルは以下のとおりです。
- Dao(Cd1Dao.class.php)
- SQLファイル(Cd1Dao_getCD1List.sql, Cd1Dao_getCD2List.sql, Cd1Dao_getCD3List.sql)
- diconファイル(example.dicon.xml)
- 共通読み込みファイル(example.inc.php)
- 実行クラス<検索系>(cd_select1.php, cd_select2.php, cd_select3.php)
- 実行クラス<更新系>(cd_insert.php, cd_update.php, cd_delete.php)
Daoの作成
- CDテーブルと対応するBeanと関連付けをします。
- メソッドを定義します。
- 全件検索するメソッド(getAllCdArray()メソッド)
- IDが1以上のCDを検索するメソッド(getCdsArray()メソッド)
- IDを引数として、一致するCDを検索するメソッド(getSelectCdByIdArray($id)メソッド)
- IDとタイトルを引数として一致するCDを検索するメソッド(getCD1List($id, $title = null)メソッド)
- IDとタイトル、ジャンルを引数として一致するCDを検索するメソッド(getCD2List($id, $title, $content)メソッド)
- IDを引数として、一致するCDを検索するメソッド(getCD3List($id = null)メソッド)
- CDの更新を行うメソッド(update(CdBean $cd)メソッド)
- CDの追加を行うメソッド(insert(CdBean $cd)メソッド)
- CDの削除を行うメソッド(delete(CdBean $cd)メソッド)
- SQL文とメソッドの引数を関連付けするにはARGSアノテーションを使用します。
- ※List、Arrayで終わるメソッドの戻り値についてはメソッドの定義を御覧になってください
<?php
interface Cd1Dao {
const BEAN = "CdBean";
const insert_NO_PERSISTENT_PROPS = "content";
const update_NO_PERSISTENT_PROPS = "id, content";
const getSelectCdByIdArray_ARGS = "id";
const getCD1List_ARGS = "id, title";
const getCD2List_ARGS = "id, title, content";
const getCD3List_ARGS = "id";
const getCdsArray_SQL = "SELECT CD.ID, CD.TITLE FROM CD WHERE ID > 1";
const getSelectCdByIdArray_QUERY = "ID = /*id*/1";
public function update(CdBean $cd);
public function insert(CdBean $cd);
public function delete(CdBean $cd);
public function getAllCdArray();
public function getCdsArray();
public function getSelectCdByIdArray($id);
public function getCD1List($id, $title = null);
public function getCD2List($id, $title, $content);
public function getCD3List($id = null);
}
?>
SQLファイルの作成
- Daoに定義したメソッドに対応するSQLファイルをそれぞれ作成します。
- ファイル名は「クラス名_メソッド名.sql」とします。
- 動的なSQLはSQLコメントを使用して作成します。
Cd1Dao_getCD1List.sql
SELECT * FROM CD WHERE ID = 16 OR TITLE = '18';
Cd1Dao_getCD2List.sql
SELECT *
FROM CD
WHERE
ID = '1'
AND TITLE = 'bohemian rhapsody'
AND CONTENT = 'blues'
Cd1Dao_getCD3List.sql
SELECT *
FROM CD
WHERE
ID = '1'
-- ELSE ID = 1
diconファイルの作成
- dao.diconをincludeします。
- 作成したDaoのコンポーネント定義します。
- Daoにdao.interceptor(S2DaoInterceptor)を適用します。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"components21.dtd">
<components namespace="example">
<include path="DAO_DICON" />
<component name="beanCdDao" class="Cd1Dao">
<aspect>dao.interceptor</aspect>
</component>
<component name="daoImpl" class="Cd2DaoImpl">
<aspect>dao.interceptor</aspect>
</component>
</components>
共通読み込みファイル(example.inc.php)の作成
- S2Container.phpとS2Dao.phpを読み込みます。
- pdo.diconファイルまでのパスを設定します。(PDO_DICON定数)
- S2ContainerClassLoader::import()で作成したファイルを読み込ませます。
- __autoload()関数にS2ContainerClassLoader::load()を設定します。
<?php
require_once 'S2Container/S2Container.php';
require_once 'S2Dao/S2Dao.php';
define('S2CONTAINER_PHP5_LOG_LEVEL', S2Container_SimpleLogger::DEBUG);
define('DAO_DICON', dirname(dirname(__FILE__)) . '/dao.dicon');
define('PDO_DICON', dirname(dirname(__FILE__)) . '/pdo.dicon');
if(class_exists('S2ContainerClassLoader')){
S2ContainerClassLoader::import(S2CONTAINER_PHP5);
S2ContainerClassLoader::import(S2DAO_PHP5);
S2ContainerClassLoader::import(dirname(__FILE__) . "/dao");
S2ContainerClassLoader::import(dirname(__FILE__) . "/entity");
S2ContainerClassLoader::import(dirname(__FILE__) . "/impl");
function __autoload($class = null){
if(S2ContainerClassLoader::load($class)){
return;
}
}
}
?>
実行ファイルの作成
- 先に作成した共通読み込みファイル(example.inc.php)を読み込みます
- S2Container::create()メソッドの第1引数に作成したdiconファイル(example.dicon.dicon)のパスを指定してコンテナを作成します。
- S2Container::getComponent()メソッドの第1引数にコンポーネントに登録したクラス名(beanCdDao)を指定してコンポーネントを取得します。
- Daoに定義したメソッドを実行します。
検索系のサンプル
cd_select1.php
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("beanCdDao");
$cd = $dao->getAllCDArray();
for($i = 0; $i < count($cd); $i++){
echo "ID: " . $cd[$i]->getId(), PHP_EOL;
echo "TITLE: " . $cd[$i]->getTitle(), PHP_EOL;
echo "CONTENT: " . $cd[$i]->getContent(), PHP_EOL;
echo "-------", PHP_EOL;
}
echo "=====", PHP_EOL;
$cd = $dao->getSelectCdByIdArray(20);
foreach($cd as $bean){
echo "ID: " . $bean->getId(), PHP_EOL;
echo "TITLE: " . $bean->getTitle(), PHP_EOL;
echo "CONTENT: " . $bean->getContent(), PHP_EOL;
echo "-------", PHP_EOL;
}
?>
実行結果
> php cd_select1.php
[DEBUG] - SELECT CD.CONTENT, CD.ID, CD.TITLE FROM CD
ID: 1
TITLE: HeyJude
CONTENT: Rock
-------
ID: 20
TITLE: gonna rice
CONTENT:
-------
ID: 3
TITLE: あの木何の木
CONTENT: J-POP
-------
ID: 2
TITLE: ride on technology
CONTENT:
-------
=====
[DEBUG] - SELECT CD.CONTENT, CD.ID, CD.TITLE FROM CD WHERE ID = 20
ID: 20
TITLE: gonna rice
CONTENT:
-------
cd_select2.php
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("beanCdDao");
$list = $dao->getCD1List(2, 'aaa');
for($i = 0; $i < $list->size(); $i++){
$cd = $list->get($i);
echo "ID: " . $cd->getId(), PHP_EOL;
echo "TITLE: " . $cd->getTitle(), PHP_EOL;
echo "CONTENT: " . $cd->getContent(), PHP_EOL;
echo "-------", PHP_EOL;
}
echo "=====", PHP_EOL;
$list = $dao->getCD2List(2, 'help!', 'rock');
$i = $list->getIterator();
while($i->valid()){
$cd = $i->current();
echo "ID: " . $cd->getId(), PHP_EOL;
echo "TITLE: " . $cd->getTitle(), PHP_EOL;
echo "CONTENT: " . $cd->getContent(), PHP_EOL;
echo "-------", PHP_EOL;
$i->next();
}
?>
実行結果
> php cd_select2.php
[DEBUG] - SELECT * FROM CD WHERE ID = 2 OR TITLE = 'aaa'
ID: 2
TITLE: ride on technology
CONTENT:
-------
=====
[DEBUG] - SELECT *
FROM CD
WHERE
ID = 2
AND TITLE = 'help!'
AND CONTENT = 'blues'
cd_select3.php
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("beanCdDao");
$list = $dao->getCD3List(null);
$cds = $list->toArray();
for($i = 0; $i < $list->size(); $i++){
echo "ID: " . $cds[$i]->getId(), PHP_EOL;
echo "TITLE: " . $cds[$i]->getTitle(), PHP_EOL;
echo "CONTENT: " . $cds[$i]->getContent(), PHP_EOL;
echo "-------", PHP_EOL;
}
echo "======", PHP_EOL;
$cds = $dao->getCdsArray();
foreach($cds as $cd){
echo "ID: " . $cd->getId(), PHP_EOL;
echo "TITLE: " . $cd->getTitle(), PHP_EOL;
echo "CONTENT: " . $cd->getContent(), PHP_EOL;
echo "-------", PHP_EOL;
}
?>
実行結果
> php cd_select3.php
[DEBUG] - SELECT *
FROM CD
WHERE
ID = 1
ID: 1
TITLE: HeyJude
CONTENT: Rock
-------
======
[DEBUG] - SELECT CD.ID, CD.TITLE FROM CD WHERE ID > 1
ID: 2
TITLE: ride on technology
CONTENT:
-------
ID: 3
TITLE: あの木何の木
CONTENT:
-------
ID: 20
TITLE: gonna rice
CONTENT:
-------
更新系のサンプル
cd_insert.php
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("beanCdDao");
$cd = new CdBean();
$cd->setId(4);
$cd->setTitle("gonna rice");
$cd->setContent("Techno");
$dao->insert($cd);
?>
実行結果
> php cd_insert.php
[DEBUG] - INSERT INTO CD (ID, TITLE) VALUES (4, 'gonna rice')
cd_update.php
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("beanCdDao");
$cd = new CdBean();
$cd->setId(4);
$cd->setTitle("ride on technology");
$dao->update($cd);
?>
実行結果
> php cd_update.php
[DEBUG] - UPDATE CD SET TITLE = 'ride on technology' WHERE ID = 4
cd_delete.php
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("beanCdDao");
$cd = new CdBean();
$cd->setId(4);
$dao->delete($cd);
?>
実行結果
< php cd_delete.php
[DEBUG] - DELETE FROM CD WHERE ID = 4
この演習は、/examples/s2dao/以下に用意されています。
EntityManagerを用いる場合の簡単なサンプルです。
作成するファイルは以下のとおりです。
- Dao(Cd2Dao.class.php)
- S2Dao_AbstractDaoを継承したクラス(Cd2DaoImpl.class.php)
- 実行ファイル(Cd2DaoClient.php)
Daoの作成
- インターフェース名は"Dao"で終わらす必要があります
- CDテーブルと対応するBeanと関連付けをします。
- メソッドを定義します。IDを引数に検索するメソッド(getCd($id))
<?php
interface Cd2Dao {
const BEAN = "CdBean";
public function getCd($id);
}
?>
S2Dao_AbstractDaoを継承したクラスの作成
- S2Dao_AbstractDaoを継承します。
- Cd2Daoをimplementsします。
- geCdメソッドを実装します。
IDを指定して検索をします。
<?php
class Cd2DaoImpl extends S2Dao_AbstractDao implements Cd2Dao {
public function __construct(S2Dao_DaoMetaDataFactory $daoMetaDataFactory){
parent::__construct($daoMetaDataFactory);
}
public function getCd($id){
return $this->getEntityManager()->find("ID = ?", $id);
}
}
?>
実行ファイルの作成
- 先に作成した共通読み込みファイル(example.inc.php)を読み込みます
- S2Container::create()メソッドの第1引数に作成したdiconファイル(example.dicon.dicon)のパスを指定してコンテナを作成します。
- S2Container::getComponent()メソッドの第1引数にコンポーネントに登録したクラス名(beanCdDao)を指定してコンポーネントを取得します。
- IDに2を指定します。
- Daoに定義したメソッドを実行します。
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/example.dicon.xml");
$dao = $container->getComponent("daoImpl");
var_dump($dao->getCd(2));
?>
実行結果
> php Cd2DaoClient.class.php
[DEBUG] - SELECT CD.CONTENT, CD.ID, CD.TITLE FROM CD WHERE ID = 2
object(S2Dao_ArrayList)#259 (1) {
[0]=>
object(CdBean)#260 (3) {
["id:private"]=>
string(1) "2"
["title:private"]=>
string(18) "ride on technology"
["content:private"]=>
string(0) ""
}
}
この演習は、/examples/s2dao/以下に用意されています。
S2Dao.PHP5の簡単なExampleを全てコメントアノテーションで実行します。
コメントアノテーションを行うにあたって変更するファイルは以下です。
- 共通読み込みファイル(example.inc.php)
- Dao(CdDao.class.php)
- Entity(CdBean.class.php)
- SQLバインド変数によってコメントアノテーションのできないSQLについてはファイル(.sql)化
example.inc.phpの変更
<?php
require_once 'S2Container/S2Container.php';
require_once 'S2Dao/S2Dao.php';
define('S2CONTAINER_PHP5_LOG_LEVEL', S2Container_SimpleLogger::DEBUG);
define('DAO_DICON', dirname(dirname(__FILE__)) . '/dao.dicon');
define('PDO_DICON', dirname(dirname(__FILE__)) . '/pdo.dicon');
define('S2DAO_PHP5_USE_COMMENT', true);
if(class_exists('S2ContainerClassLoader')){
S2ContainerClassLoader::import(S2CONTAINER_PHP5);
S2ContainerClassLoader::import(dirname(__FILE__) . "/dao");
S2ContainerClassLoader::import(dirname(__FILE__) . "/entity");
function __autoload($class = null){
if(S2ContainerClassLoader::load($class)){
return;
}
}
}
?>
Dao(CdDao.class.php)の変更
<?php
/**
* @author nowel
* @Dao(bean = CdBean)
*/
interface CdDao {
/**
* @NoPersistentProperty("id, content")
*/
public function update(CdBean $cd);
/**
* @NoPersistentProperty("content")
*/
public function insert(CdBean $cd);
public function delete(CdBean $cd);
/**
* @return array
*/
public function getAll();
/**
* @Sql("SELECT CD.ID, CD.TITLE FROM CD WHERE ID > 1")
* @return array
*/
public function getCds();
/**
* @return array
*/
public function getSelectCdById($id);
/**
* @return list
*/
public function getCD1($id, $title = null);
/**
* @return list
*/
public function getCD2($id, $title, $content);
/**
* @return list
*/
public function getCD3($id = null);
/**
* @Sql("SELECT COUNT(*) FROM CD", dbms = mysql)
*/
public function getCdCount();
}
?>
Entity(CdBean.class.php)の変更
<?php
/**
* @author nowel
* @Bean(table = CD)
*/
class CdBean {
/**
* @Column("ID")
*/
private $id;
/**
* @Column("TITLE")
*/
private $title;
/**
* @Column("CONTENT")
*/
private $content;
public function getContent() {
return $this->content;
}
public function setContent($content) {
$this->content = $content;
}
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
}
}
?>
SQLファイルの追加および変更
SQLコメントにてバインドを行うとPHPコメントと衝突してしまい正しく記述できない場合があります。
その場合はSQLファイルにしておくのがよいでしょう
SQLファイルについてはメソッド名と同一にするため、ファイル名にList、Arrayを付与する必要はありません。
- CdDao_getCD1.sql
- CdDao_getCD2.sql
- CdDao_getCD3.sql
- CdDao_getSelectCdById.sql
CdDao_getCD1.sql
SELECT * FROM CD WHERE ID = 16 OR TITLE = '18';
CdDao_getCD2.sql
SELECT * FROM CD
WHERE
ID = '1'
AND TITLE = 'bohemian rhapsody'
AND CONTENT = 'blues'
CdDao_getCD3.sql
SELECT *
FROM CD
WHERE
/*IF id != null*/ ID = /*id*/'1'
--ELSE ID = 1
/*END*/
CdDao_getSelectCdById.sql
select * from CD where ID = 1
実行結果
cd_select1.php
[DEBUG] - SELECT CD.CONTENT, CD.ID, CD.TITLE FROM CD
ID: 1
TITLE: S2Dao!!!
CONTENT: hello!!
-------
=====
[DEBUG] - select * from CD where ID = 1
ID: 1
TITLE: S2Dao!!!
CONTENT: hello!!
-------
cd_select2.php
[DEBUG] - SELECT * FROM CD WHERE ID = 2 OR TITLE = 'aaa'
=====
[DEBUG] - SELECT * FROM CD
WHERE
ID = 2
AND TITLE = 'help!'
AND CONTENT = 'blues'
cd_select3.php
[DEBUG] - SELECT *
FROM CD
WHERE
ID = 1
object(S2Dao_ArrayList)#345 (1) {
[0]=>
object(CdBean)#348 (3) {
["id:private"]=>
string(1) "1"
["title:private"]=>
string(8) "S2Dao!!!"
["content:private"]=>
string(7) "hello!!"
}
}
ID: 1
TITLE: S2Dao!!!
CONTENT: hello!!
-------
======
cd_getCount.php
[DEBUG] - SELECT COUNT(*) FROM CD
int(1)
cd_insert.php
[DEBUG] - INSERT INTO CD (ID, TITLE) VALUES (2, 'gonna rice')
cd_update.php
[DEBUG] - UPDATE CD SET TITLE = 'ride on technology' WHERE ID = 2
cd_delete.php
[DEBUG] - DELETE FROM CD WHERE ID = 2
定数アノテーション時と同じ結果が取れたことが確認できました。
この演習は、/examples/s2dao_comment/以下に用意されています。
Example2(Java版S2DaoのExample)
このExampleは前提条件として以下のテーブル、Beanを使用します。
テーブル:EMP
カラム名 |
論理名 |
型 |
NotNull |
主キー |
EMPNO |
従業員番号 |
INTEGER |
〇 |
〇 |
ENAME |
従業員名 |
VARCHAR |
|
|
JOB |
仕事 |
VARCHAR |
|
|
MGR |
上司 |
INTEGER |
|
|
HIREDATE |
雇用日 |
DATE |
|
|
SAL |
給料 |
NUMBER |
|
|
COMM |
手数料 |
NUMBER |
|
|
DEPTNO |
部署番号 |
INTEGER |
|
|
テーブル:DEPT
カラム名 |
論理名 |
型 |
NotNull |
主キー |
DEPTNO |
部署番号 |
INTEGER |
〇 |
〇 |
DNAME |
部署名 |
VARCHAR |
|
|
LOC |
ロケーション |
VARCHAR |
|
|
VERSIONNO |
バージョン番号 |
INTEGER |
|
|
EMPテーブルに関連付くBeanは次の通りです。
<?php
class Employee implements Serializable {
const TABLE = "EMP";
const department_RELNO = 0;
const timestamp_COLUMN = "tstamp";
private $empno;
private $ename;
private $job;
private $mgr;
private $hiredate;
private $sal;
private $comm;
private $deptno;
private $timestamp;
private $department;
public function serialize(){
$prop = array();
foreach(get_class_vars(__CLASS__) as $key => $value){
$prop[$key] = $value;
}
return serialize($prop);
}
public function unserialize($serialized){
foreach(unserialize($serialized) as $key => $value){
$this->$key = $value;
}
}
public function __construct($empno = null) {
if(!is_null($empno)){
$this->empno = $empno;
}
}
public function getEmpno() {
return $this->empno;
}
public function setEmpno($empno) {
$this->empno = $empno;
}
public function getEname() {
return $this->ename;
}
public function setEname($ename) {
$this->ename = $ename;
}
public function getJob() {
return $this->job;
}
public function setJob($job) {
$this->job = $job;
}
public function getMgr() {
return $this->mgr;
}
public function setMgr($mgr) {
$this->mgr = $mgr;
}
public function getHiredate() {
return $this->hiredate;
}
public function setHiredate($hiredate) {
$this->hiredate = $hiredate;
}
public function getSal() {
return $this->sal;
}
public function setSal($sal) {
$this->sal = $sal;
}
public function getComm() {
return $this->comm;
}
public function setComm($comm) {
$this->comm = $comm;
}
public function getDeptno() {
return $this->deptno;
}
public function setDeptno($deptno) {
$this->deptno = $deptno;
}
public function getTimestamp() {
return $this->timestamp;
}
public function setTimestamp($timestamp) {
$this->timestamp = $timestamp;
}
public function getDepartment() {
return $this->department;
}
public function setDepartment(Department $department) {
$this->department = $department;
}
public function equals($other) {
if (!($other instanceof Employee)) return false;
return $this->getEmpno() == $other->getEmpno();
}
public function toString() {
$buf = $this->empno . ", ";
$buf .= $this->ename . ", ";
$buf .= $this->job . ", ";
$buf .= $this->mgr . ", ";
$buf .= $this->hiredate . ", ";
$buf .= $this->sal . ", ";
$buf .= $this->comm . ", ";
$buf .= $this->deptno . ", ";
$buf .= $this->timestamp . " {";
if($this->department != null){
$buf .= $this->department->toString();
} else {
$buf .= "null";
}
$buf .= "}";
return $buf;
}
public function hashCode() {
return $this->getEmpno();
}
}
?>
DEPTテーブルに関連付くBeanは次の通りです。
<?php
class Department implements Serializable {
const TABLE = "DEPT";
private $deptno;
private $dname;
private $loc;
private $versionNo;
public function __construct() {
}
public function serialize(){
return serialize(array(
"deptno" => $this->deptno,
"dname" => $this->dname,
"loc" => $this->loc,
"versionNo" => $this->versionNo,
));
}
public function unserialize($serialized){
foreach(unserialize($serialized) as $key => $value){
$this->$key = $value;
}
}
public function getDeptno() {
return $this->deptno;
}
public function setDeptno($deptno) {
$this->deptno = $deptno;
}
public function getDname() {
return $this->dname;
}
public function setDname($dname) {
$this->dname = $dname;
}
public function getLoc() {
return $this->loc;
}
public function setLoc($loc) {
$this->loc = $loc;
}
public function getVersionNo() {
return $this->versionNo;
}
public function setVersionNo($versionNo) {
$this->versionNo = $versionNo;
}
public function equals($other) {
if (!($other instanceof Department) ) return false;
return $this->getDeptno() == $other->getDeptno();
}
public function toString() {
$buf = $this->deptno . ", ";
$buf .= $this->dname . ", ";
$buf .= $this->loc . ", ";
$buf .= $this->versionNo;
return $buf;
}
public function hashCode() {
return $this->getDeptno();
}
}
?>
SQLファイルを作成し、Daoから記述したSQL文を実行する演習です。
作成するファイルは以下のとおりです。
- Dao(EmployeeDao.class.php)
- SQLファイル(EmployeeDao_getAllEmployeesList.sql, EmployeeDao_getEmployee.sql, EmployeeDao_getCount.sql, EmployeeDao_getEmployeeByJobDeptnoList.sql, EmployeeDao_update.sql)
- diconファイル(EmployeeDao.dicon)
- 実行クラス(EmployeeDaoClient.class.php)
Daoの作成
- EMPテーブルと対応するEntity(Bean)と関連付けをします。
- メソッドを定義します。
全件検索するメソッド(getAllEmployeesList()メソッド)
従業員番号を引数として、一致する従業員を検索するメソッド(getEmployee($empno)メソッド)
従業員をカウントするメソッド(getCount()メソッド)
仕事と部署番号を引数として、一致する従業員を検索するメソッド(getEmployeeByJobDeptnoList($job, $deptno)メソッド)
従業員を更新するメソッド(update(Employee $employee)メソッド)
- SQL文とメソッドの引数を関連付けするにはARGSアノテーションを使用します。
- EMPテーブルの件数を取得するgetCount()メソッドは、1行でテーブルの件数が返ってくるので戻り値をintとします。
<?php
interface EmployeeDao {
const BEAN = "Employee";
public function getAllEmployeesList();
public function getEmployee($empno);
public function getCount();
public function getEmployeeByJobDeptnoList($job, $deptno);
const getEmployeeByDeptnoList_QUERY = "
/*IF deptno !== null*/EMP.DEPTNO = /*deptno*/123
--ELSE 1 = 1
/*END*/";
public function getEmployeeByDeptnoList($deptno);
public function update(Employee $employee);
}
?>
SQLファイルの作成
- Daoに定義したメソッドに対応するSQLファイルをそれぞれ作成します。
- ファイル名は「クラス名_メソッド名.sql」とします。
- 動的なSQLはSQLコメントを使用して作成します。
EmployeeDao_getAllEmployeesList.sql
SELECT emp.*, dept.dname dname_0, dept.loc loc_0 FROM EMP as emp, DEPT as dept
WHERE emp.deptno = dept.deptno ORDER BY emp.empno
EmployeeDao_getEmployee.sql
SELECT EMP.*, DEPT.dname dname_0, DEPT.loc loc_0 FROM EMP, DEPT
WHERE EMP.empno = 7788 AND EMP.deptno = DEPT.deptno
EmployeeDao_getCount.sql
SELECT count(*) FROM emp
EmployeeDao_getEmployeeByJobDeptnoList.sql
SELECT * FROM EMP
WHERE
EMP.JOB = 'CLERK'
AND EMP.DEPTNO = 20
EmployeeDao_update.sql
UPDATE EMP SET ename = /*employee.ename*/'SCOTT'
WHERE empno = /*employee.empno*/7788
diconファイルの作成
- dao.diconをincludeします。
- 作成したDaoのコンポーネント定義します。
- Daoにdao.interceptor(S2DaoInterceptor)を適用します。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components>
<include path="DAO_DICON" />
<component class="EmployeeDao">
<aspect>dao.interceptor</aspect>
</component>
</components>
実行ファイルの作成
- org.seasar.framework.container.S2Container#create()メソッドの第1引数に作成したdiconファイル(EmployeeDao.dicon)のパスを指定してコンテナを作成します。
- org.seasar.framework.container.S2Container#getComponent()メソッドの第1引数にコンポーネントに登録したクラス名(EmployeeDao)を指定してコンポーネントを取得します。
- Daoに定義したメソッドを実行します。
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/EmployeeDao.dicon");
$dao = $container->getComponent("EmployeeDao");
$employees = $dao->getAllEmployeesList();
for ($i = 0; $i < $employees->size(); ++$i) {
var_dump($employees->get($i)->toString());
}
$employee = $dao->getEmployee(7788);
var_dump($employee->toString());
$count = $dao->getCount();
var_dump("count:" . $count);
$dao->getEmployeeByJobDeptnoList(null, null);
$dao->getEmployeeByJobDeptnoList("CLERK", null);
$dao->getEmployeeByJobDeptnoList(null, 20);
$dao->getEmployeeByJobDeptnoList("CLERK", 20);
$dao->getEmployeeByDeptnoList(20);
$dao->getEmployeeByDeptnoList(null);
var_dump("updatedRows:" . $dao->update($employee));
$container->destroy();
?>
実行結果
> php EmployeeDaoClient.class.php
[DEBUG] - SELECT emp.*, dept.dname as dname_0, dept.loc as loc_0 FROM EMP as emp, DEPT as dept
WHERE emp.deptno = dept.deptno ORDER BY emp.empno
string(96) "7369, SMITH, CLERK, 7902, 1980-12-17, 800.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(104) "7499, ALLEN, SALESMAN, 7698, 1981-02-20, 1600.00, 300.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(103) "7521, WARD, SALESMAN, 7698, 1981-02-22, 1250.00, 500.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(99) "7566, JONES, MANAGER, 7839, 1981-04-02, 2975.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(106) "7654, MARTIN, SALESMAN, 7698, 1981-09-28, 1250.00, 1400.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(97) "7698, BLAKE, MANAGER, 7839, 1981-05-01, 2850.00, , 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(103) "7782, CLARK, MANAGER, 7839, 1981-06-09, 2450.00, , 10, 2000-01-01 00:00:00 {10, ACCOUNTING, NEW YORK, }"
string(99) "7788, SCOTT, ANALYST, 7566, 1982-12-09, 3000.00, , 20, 2006-05-14 10:30:16 {20, RESEARCH, DALLAS, }"
string(100) "7839, KING, PRESIDENT, , 1981-11-17, 5000.00, , 10, 2000-01-01 00:00:00 {10, ACCOUNTING, NEW YORK, }"
string(103) "7844, TURNER, SALESMAN, 7698, 1981-09-08, 1500.00, 0.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(97) "7876, ADAMS, CLERK, 7788, 1983-01-12, 1100.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(94) "7900, JAMES, CLERK, 7698, 1981-12-03, 950.00, , 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(98) "7902, FORD, ANALYST, 7566, 1981-12-03, 3000.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(102) "7934, MILLER, CLERK, 7782, 1982-01-23, 1300.00, , 10, 2000-01-01 00:00:00 {10, ACCOUNTING, NEW YORK, }"
[DEBUG] - SELECT EMP.*, DEPT.dname as dname_0, DEPT.loc as loc_0 FROM EMP, DEPT
WHERE EMP.empno = 7788 AND EMP.deptno = DEPT.deptno
tring(97) "7788, SCOTT, ANALYST, 7566, 1982-12-09, 3000.00, , 20, 2006-05-14 10:30:16 {, RESEARCH, DALLAS, }"
[DEBUG] - SELECT count(*) FROM EMP
string(8) "count:14"
[DEBUG] - SELECT * FROM EMP
[DEBUG] - SELECT * FROM EMP
WHERE
EMP.JOB = 'CLERK'
[DEBUG] - SELECT * FROM EMP
WHERE
EMP.DEPTNO = 20
[DEBUG] - SELECT * FROM EMP
WHERE
EMP.JOB = 'CLERK'
AND EMP.DEPTNO = 20
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm, EMP.deptno,
EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0, department.loc AS loc_0,
department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno WHERE
EMP.DEPTNO = 20
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm, EMP.deptno,
EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0, department.loc AS loc_0,
department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno WHERE
1 = 1
[DEBUG] - UPDATE EMP SET ename = 'SCOTT'
WHERE empno = 7788
string(13) "updatedRows:1"
"updatedRows"の値から更新された件数を確認することができます。
この演習は、/examples/s2dao_java_orign以下に用意されています。
自動で更新処理(UPDATE, INSERT, DELETE)のSQL文の生成とVersionNoによる排他制御の演習です。SQLファイルの作成は不要です。
作成するファイルは以下のとおりです。
- Dao(DepartmentDao.class.php)
- diconファイル(DepartmentDao.dicon)
- 実行クラス(DepartmentDaoClient.class.php)
Daoの作成
- DEPTテーブルと対応するBeanと関連付けをします。
- 更新処理を行うメソッドを定義します。
部署を追加するメソッド(insert(Department department)メソッド)
部署を更新するメソッド(update(Department department)メソッド)
部署を削除するメソッド(delete(Department department)メソッド)
<?php
interface DepartmentDao {
const BEAN = "Department";
public function insert(Department $department);
public function update(Department $department);
public function delete(Department $department);
}
?>
diconファイルの作成
- dao.diconをincludeします。
- 作成したDaoのコンポーネント定義します。
- Daoにdao.interceptor(S2DaoInterceptor)を適用します。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components>
<include path="DAO_DICON" />
<component class="DepartmentDao">
<aspect>dao.interceptor</aspect>
</component>
</components>
実行ファイルの作成
- S2Container::create()メソッドの第1引数に作成したdiconファイル(DepartmentDao.dicon)のパスを指定してコンテナを作成します。
- S2Container::getComponent()メソッドの第1引数にコンポーネントに登録したクラス名(DepartmentDao)を指定してコンポーネントを取得します。
- Daoに定義したメソッドを実行します。
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/DepartmentDao.dicon");
$dao = $container->getComponent("DepartmentDao");
$dept = new Department();
$dept->setDeptno(99);
$dept->setDname("foo");
$dao->insert($dept);
$dept->setDname("bar");
echo "before update versionNo:" . $dept->getVersionNo(), PHP_EOL;
$dao->update($dept);
echo "after update versionNo:" . $dept->getVersionNo(), PHP_EOL;
$dao->delete($dept);
$container->destroy();
?>
実行結果
> php DepartmentDaoClient.php
[DEBUG] - INSERT INTO DEPT (DEPTNO, DNAME, LOC, VERSIONNO) VALUES (99, 'foo', null, 0)
before update versionNo:0
[DEBUG] - UPDATE DEPT SET DNAME = 'bar', LOC = null, VERSIONNO = 1 WHERE DEPTNO = 99 AND VERSIONNO = 0
after update versionNo:1
[DEBUG] - DELETE FROM DEPT WHERE DEPTNO = 99 AND VERSIONNO = 1
出力結果を見ると、自動的にSQL文が発行されていることが分かります。
またBean(Department)にはint型のプロパティversionNoが定義してあるので、
自動でversionNoの値が+1され、この値によって排他制御されていることがわかります。
updateメソッドを呼ぶ以前では、versionNoの値は0ですが、updateメソッドを呼び出した後では、値が1になります。
この演習は、/examples/s2dao_java_orign以下に用意されています。
自動でSELECT文の生成とTimestampによる自動排他制御を行う演習です。
SQLファイルの作成は不要です。また引数にDTOを使用するメソッドも定義してみましょう。
作成するファイルは以下のとおりです。
- Dao(EmployeeAutoDao.class.php)
- DTO(EmployeeSearchCondition.class.php)
- diconファイル(EmployeeAutoDao.dicon)
- 実行クラス(EmployeeAutoDaoClient.php)
Daoの作成
- EMPテーブルと対応するBeanと関連付けをします。
- メソッドを定義します。
全件検索するメソッド(getAllEmployees()メソッド)
仕事と部署番号を引数として、一致する従業員を検索するメソッド(getEmployeeByJobDeptno($job = null, $deptno = null)メソッド)
従業員番号を引数として、一致する従業員を検索するメソッド(getEmployeeByEmpno($empno)メソッド)
指定した給料の間に含まれる従業員を検索するメソッド(getEmployeesBySal($minSal, $maxSal)メソッド)
指定した部署と一致する従業員を検索するメソッド(getEmployeeByDname($dname)メソッド)
DTOを引数とした従業員の検索をするメソッド(getEmployeesBySearchCondition(EmployeeSearchCondition $dto)メソッド)
従業員を更新するメソッド(update(Employee $employee)メソッド)
<?php
interface EmployeeAutoDao {
const BEAN = "Employee";
public function getAllEmployeesList();
public function getEmployeeByJobDeptnoList($job = null, $deptno = null);
public function getEmployeeByEmpno($empno);
const getEmployeesBySalList_QUERY = "EMP.sal BETWEEN ? AND ? ORDER BY EMP.empno";
public function getEmployeesBySalList($minSal, $maxSal);
public function getEmployeeByDnameList($dname_0);
public function getEmployeesBySearchConditionList(EmployeeSearchCondition $dto);
public function update(Employee $employee);
}
?>
DTOの作成
<?php
class EmployeeSearchCondition {
const dname_COLUMN = "dname_0";
private $job;
private $dname;
public function getDname() {
return $this->dname;
}
public function setDname($dname) {
$this->dname = $dname;
}
public function getJob() {
return $this->job;
}
public function setJob($job) {
$this->job = $job;
}
}
?>
diconファイルの作成
- dao.diconをincludeします。
- 作成したDaoのコンポーネント定義します。
- Daoにdao.interceptor(S2DaoInterceptor)を適用します。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components>
<include path="%DAO_DICON%" />
<component class="EmployeeAutoDao">
<aspect>dao.interceptor</aspect>
</component>
</components>
実行ファイルの作成
- S2Container#create()メソッドの第1引数に作成したdiconファイル(EmployeeAutoDao.dicon)のパスを指定してコンテナを作成します。
- S2Container#getComponent()メソッドの第1引数にコンポーネントに登録したクラス名(EmployeeAutoDao)を指定してコンポーネントを取得します。
- Daoに定義したメソッドを実行します。
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/EmployeeAutoDao.dicon");
$dao = $container->getComponent("EmployeeAutoDao");
$dao->getEmployeeByJobDeptnoList(null, null);
$dao->getEmployeeByJobDeptnoList("CLERK", null);
$dao->getEmployeeByJobDeptnoList(null, 20);
$dao->getEmployeeByJobDeptnoList("CLERK", 20);
$employees = $dao->getEmployeesBySalList(0, 1000);
for ($i = 0; $i < $employees->size(); ++$i) {
var_dump($employees->get($i)->toString());
}
$employees = $dao->getEmployeeByDnameList("SALES");
for ($i = 0; $i < $employees->size(); ++$i) {
var_dump($employees->get($i)->toString());
}
$dto = new EmployeeSearchCondition();
$dto->setDname("RESEARCH");
$employees = $dao->getEmployeesBySearchConditionList($dto);
for ($i = 0; $i < $employees->size(); ++$i) {
var_dump($employees->get($i)->toString());
}
$employee = $dao->getEmployeeByEmpno(7788);
var_dump("before timestamp:" . $employee->getTimestamp());
$dao->update($employee);
var_dump("after timestamp:" . $employee->getTimestamp());
$container->destroy();
?>
実行結果
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm,
EMP.deptno, EMP.tstamp, department.deptno AS deptno_0,
department.dname AS dname_0, department.loc AS loc_0, department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm,
EMP.deptno, EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0, department.loc AS loc_0,
department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
WHERE EMP.job = 'CLERK'
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm,
EMP.deptno, EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0, department.loc AS loc_0,
department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
WHERE EMP.job = '' AND EMP.deptno = 20
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm,
EMP.deptno, EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0, department.loc AS loc_0,
department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
WHERE EMP.job = 'CLERK' AND EMP.deptno = 20
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal,
EMP.comm, EMP.deptno, EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0,
department.loc AS loc_0, department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
WHERE EMP.sal BETWEEN 0 AND 1000 ORDER BY EMP.empno
string(96) "7369, SMITH, CLERK, 7902, 1980-12-17, 800.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(94) "7900, JAMES, CLERK, 7698, 1981-12-03, 950.00, , 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal,
EMP.comm, EMP.deptno, EMP.tstamp, department.deptno AS deptno_0,
department.dname AS dname_0, department.loc AS loc_0, department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
string(96) "7369, SMITH, CLERK, 7902, 1980-12-17, 800.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(104) "7499, ALLEN, SALESMAN, 7698, 1981-02-20, 1600.00, 300.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(103) "7521, WARD, SALESMAN, 7698, 1981-02-22, 1250.00, 500.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(99) "7566, JONES, MANAGER, 7839, 1981-04-02, 2975.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(106) "7654, MARTIN, SALESMAN, 7698, 1981-09-28, 1250.00, 1400.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(97) "7698, BLAKE, MANAGER, 7839, 1981-05-01, 2850.00, , 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(103) "7782, CLARK, MANAGER, 7839, 1981-06-09, 2450.00, , 10, 2000-01-01 00:00:00 {10, ACCOUNTING, NEW YORK, }"
string(100) "7839, KING, PRESIDENT, , 1981-11-17, 5000.00, , 10, 2000-01-01 00:00:00 {10, ACCOUNTING, NEW YORK, }"
string(103) "7844, TURNER, SALESMAN, 7698, 1981-09-08, 1500.00, 0.00, 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(97) "7876, ADAMS, CLERK, 7788, 1983-01-12, 1100.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(94) "7900, JAMES, CLERK, 7698, 1981-12-03, 950.00, , 30, 2000-01-01 00:00:00 {30, SALES, CHICAGO, }"
string(98) "7902, FORD, ANALYST, 7566, 1981-12-03, 3000.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(102) "7934, MILLER, CLERK, 7782, 1982-01-23, 1300.00, , 10, 2000-01-01 00:00:00 {10, ACCOUNTING, NEW YORK, }"
string(99) "7788, SCOTT, ANALYST, 7566, 1982-12-09, 3000.00, , 20, 2006-05-14 10:30:16 {20, RESEARCH, DALLAS, }"
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm,
EMP.deptno, EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0,
department.loc AS loc_0, department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
WHERE department.dname = 'RESEARCH'
string(96) "7369, SMITH, CLERK, 7902, 1980-12-17, 800.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(99) "7566, JONES, MANAGER, 7839, 1981-04-02, 2975.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(97) "7876, ADAMS, CLERK, 7788, 1983-01-12, 1100.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(98) "7902, FORD, ANALYST, 7566, 1981-12-03, 3000.00, , 20, 2000-01-01 00:00:00 {20, RESEARCH, DALLAS, }"
string(99) "7788, SCOTT, ANALYST, 7566, 1982-12-09, 3000.00, , 20, 2006-05-16 23:38:39 {20, RESEARCH, DALLAS, }"
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm,
EMP.deptno, EMP.tstamp, department.deptno AS deptno_0, department.dname AS dname_0,
department.loc AS loc_0, department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno
WHERE EMP.empno = 7788
string(36) "before timestamp:2006-05-16 23:58:48"
[DEBUG] - UPDATE EMP SET ename = 'SCOTT', job = 'ANALYST', mgr = 7566,
hiredate = '1982-12-09', sal = '3000.00', comm = null, deptno = 20,
tstamp = '2006-05-17 00:00:41' WHERE empno = 7788 AND tstamp = '2006-05-16 23:58:48'
string(35) "after timestamp:2006-05-17 00:00:41"
出力されているログからSQL文が自動的に生成されていることがわかります。
また更新前と更新後ではTimestampの値が変化していることに気付くと思います。この値で排他制御を行っていることがわかります。
この演習は、/examples/s2dao_java_orign以下に用意されています。
EntityManagerを使用して、指定した文字列を名前に含む従業員を検索する演習です。
作成するファイルは以下のとおりです。
- Dao(Employee2Dao.class.php)
- S2Dao_AbstractDaoを継承したクラス(Employee2DaoImpl.class.php)
- diconファイル(Employee2Dao.dicon)
- 実行クラス(Employee2DaoClient.class.php)
Daoの作成
- なお、インターフェース名は"Dao"で終わらす必要があります。
- EMPテーブルと対応するBeanと関連付けをします。
- 検索処理を行うメソッドを定義します。
従業員を検索するメソッド(getEmployees(String ename))
<?php
interface Employee2Dao {
public function getEmployees($ename);
public function getEmployee($eno);
}
?>
AbstractDaoを継承したクラスの作成
- S2Dao_AbstractDaoを継承します。
- Employee2Daoをimplementsします。
- getEmployeesメソッドを実装します。指定した文字列を名前に含む検索をします。
<?php
class Employee2DaoImpl extends S2Dao_AbstractDao implements Employee2Dao {
const BEAN = "Employee";
public function __construct(S2Dao_DaoMetaDataFactory $daoMetaDataFactory){
parent::__construct($daoMetaDataFactory);
}
public function getEmployees($ename) {
return $this->getEntityManager()->find("EMP.ename LIKE ? ", "%" . $ename . "%");
}
public function getEmployee($eno){
return $this->getEntityManager()->find(
"SELECT * FROM EMP WHERE EMPNO = ?", $eno);
}
}
?>
diconファイルの作成
- dao.diconをincludeします。
- AbstractDaoを継承したクラスをコンポーネント定義します。
- 登録したコンポーネントにdao.interceptor(S2DaoInterceptor)を適用します。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components>
<include path="DAO_DICON" />
<component class="Employee2DaoImpl">
<aspect>dao.interceptor</aspect>
</component>
</components>
実行ファイルの作成
- S2Container::create()メソッドの第1引数に作成したdiconファイル(Employee2Dao.dicon)のパスを指定してコンテナを作成します。
- S2Container::getComponent()メソッドの第1引数にコンポーネントに登録したクラス名(Employee2Dao)を指定してコンポーネントを取得します。
- "CO"を名前に含むという条件を指定します。
- Daoに定義したメソッドを実行します。
<?php
require_once dirname(__FILE__) . "/example.inc.php";
$container = S2ContainerFactory::create("./resource/Employee2Dao.dicon");
$dao = $container->getComponent("Employee2Dao");
$employees = $dao->getEmployees("CO");
for ($i = 0; $i < $employees->size(); ++$i) {
var_dump($employees->get($i)->toString());
}
$employee = $dao->getEmployee(7788);
var_dump($employee[0]->toString());
$container->destroy();
?>
実行結果
> php Employee2DaoClient.class.php
[DEBUG] - SELECT EMP.empno, EMP.ename, EMP.job, EMP.mgr, EMP.hiredate, EMP.sal, EMP.comm, EMP.deptno, EMP.tstamp,
department.deptno AS deptno_0, department.dname AS dname_0,
department.loc AS loc_0, department.versionno AS versionno_0
FROM EMP LEFT OUTER JOIN DEPT department ON EMP.deptno = department.deptno WHERE EMP.ename LIKE '%CO%'
string(99) "7788, SCOTT, ANALYST, 7566, 1982-12-09, 3000.00, , 20, 2006-05-14 10:30:16 {20, RESEARCH, DALLAS, }"
[DEBUG] - SELECT * FROM EMP WHERE EMPNO = 7788
string(85) "7788, SCOTT, ANALYST, 7566, 1982-12-09, 3000.00, , 20, 2006-05-14 10:30:16 {20, , , }"
※[DEBUG]表示において不要な部分は削除しています。
この演習は、/examples/s2dao_java_orign以下に用意されています。
|
|