Polymorphicの実験(1) @Polymorphicと@ManyToManyを組み合わせる。

ActiveObjectsのPolymorphicアノテーションの挙動を理解するために、いろいろな使い方を試してみようと思います。
これから何回か「Polymorphicの実験」というタイトルで、他のアノテーションとの組み合わせ等、試していきます。

今回は、多対多&ポリモフィックを試しました。

概要

まず、UserとComputerが多対多で関連するとします。
あるUserは複数のComputerを使用し、同じPCを使用するUserが複数人いるような場合です。

さらに、Computerには具体的にいくつかの種類があるとします。
Computerというのは大雑把な言い方で、もっと具体的に言えばPCやMacになるというような場合です。

このような条件から、ActiveObjectsのエンティティを作成し、さらにそのエンティティを操作するプログラムを作成しました。

記載項目

エンティティの関連図 作成したエンティティの関連図。上記の条件を満たします。
DBに格納されたデータ エンティティ関連を反映したテーブル構造とデータ内容になっています。
ソースファイル 実行したプログラムです。
System.out.println()の出力結果 プログラムの出力結果です。
SQLが発行された順序 プログラムの実行により発行されたSQLを順に並べています。

以下、上記の表に挙げた項目が、続きます。

エンティティの関連図


DBに格納されたデータ

mac
id speed
1 150
pc
id speed
1 80
person
id 他カラムなし
1 -
2 -
persontocomputer
id personID computerID computerType
1 1 1 ao_test.Mac
2 2 1 ao_test.PC
3 2 1 ao_test.Mac

ソースファイル

package ao_test;

import net.java.ao.EntityManager;
import java.sql.SQLException;

public class Driver {

        public static void main( String args ) throws SQLException {
                EntityManager manager = new EntityManager("jdbc:mysql://192.168.1.19/ao_test", "root", "root");

                // ログ出力。
                java.util.logging.Logger.getLogger("net.java.ao").setLevel(java.util.logging.Level.FINE);

                // 1.マイグレーション
                manager.migrate( Person.class, Computer.class, Mac.class, PC.class, PersonToComputer.class );

                // 2.エンティティを作成する。
                create( manager );

                // 3.エンティティを取得して表示する。
                print( manager );
        }

        // 2.エンティティを作成する。
        private static void create( EntityManager manager ) throws SQLException {
                // 2.1.Macのエンティティを作成する。
                Mac mac = manager.create( Mac.class );
                mac.setSpeed( 150 );
                mac.save();

                // 2.2.PCをのエンティティ作成する。
                PC pc = manager.create( PC.class );
                pc.setSpeed( 80 );
                pc.save();

                // 2.3.Personのエンティティ作成する。
                Person macUser = manager.create( Person.class );
                macUser.save();

                Person pcUser = manager.create( Person.class );
                pcUser.save();

                // 2.4.PersonとPCの関連のエンティティを作成する。
                PersonToComputer to1 = manager.create( PersonToComputer.class );
                to1.setPerson( macUser );
                to1.setComputer( mac );
                to1.save();

                PersonToComputer to2 = manager.create( PersonToComputer.class );
                to2.setPerson( pcUser );
                to2.setComputer( pc );
                to2.save();

                PersonToComputer to3 = manager.create( PersonToComputer.class );
                to3.setPerson( pcUser );
                to3.setComputer( mac );
                to3.save();
        }

        // 3.エンティティを取得して表示する。
        private static void print( EntityManager manager ) throws SQLException {

                // 3.1.Personのエンティティをすべて取得する。
                Person people = manager.find( Person.class );

                // 3.2.Personのエンティティについて繰り返す。
                for ( Person person : people ) {
                        System.out.println( "person.toString() : " + person.toString() );

                        // 3.2.1.Personのエンティティに関連するComputerのエンティティを取得する。
                        Computer[] computers = person.getComputers();

                        // 3.2.2.Computerのエンティティについて繰り返す。
                        for ( Computer computer : computers ) {
                                System.out.println( "\tcomputer.toString(): " + computer.toString() );
                                System.out.println( "\tcomputer.getSpeed(): " + computer.getSpeed() );
                        }
                }
        }
}

System.out.println()の出力結果

person.toString() : person {id = 1}
        computer.toString(): mac {id = 1}
        computer.getSpeed(): 150.0
person.toString() : person {id = 2}
        computer.toString(): pC {id = 1}
        computer.getSpeed(): 80.0
        computer.toString(): mac {id = 1}
        computer.getSpeed(): 150.0

SQLが発行された順序

// 1.マイグレーション
CREATE TABLE person (
    id INTEGER AUTO_INCREMENT NOT NULL,
    PRIMARY KEY(id)
) ENGINE=InnoDB

CREATE TABLE personToComputer (
    id INTEGER AUTO_INCREMENT NOT NULL,
    personID INTEGER,
    computerID INTEGER,
    computerType VARCHAR(127),
    CONSTRAINT fk_persontocomputer_personid FOREIGN KEY (personID) REFERENCES person(id),
    PRIMARY KEY(id)
) ENGINE=InnoDB

CREATE INDEX index_persontocomputer_personid ON personToComputer(personID)

CREATE INDEX index_persontocomputer_computerid ON personToComputer(computerID)

CREATE TABLE mac (
    id INTEGER AUTO_INCREMENT NOT NULL,
    speed FLOAT,
    PRIMARY KEY(id)
) ENGINE=InnoDB

CREATE TABLE pC (
    id INTEGER AUTO_INCREMENT NOT NULL,
    speed FLOAT,
    PRIMARY KEY(id)
) ENGINE=InnoDB

// 2.エンティティを作成する。
	// 2.1.Macのエンティティを作成する。
	INSERT INTO mac (id) VALUES (DEFAULT)
	UPDATE mac SET speed = ? WHERE id = ?
	
	// 2.2.PCをのエンティティ作成する。
	INSERT INTO pC (id) VALUES (DEFAULT)
	UPDATE pC SET speed = ? WHERE id = ?
	
	// 2.3.Personのエンティティ作成する。
	INSERT INTO person (id) VALUES (DEFAULT)
	INSERT INTO person (id) VALUES (DEFAULT)
	
	// 2.4.PersonとPCの関連のエンティティを作成する。
	INSERT INTO personToComputer (id) VALUES (DEFAULT)
	UPDATE personToComputer SET computerid = ?,computertype = ?,personid = ? WHERE id = ?
	INSERT INTO personToComputer (id) VALUES (DEFAULT)
	UPDATE personToComputer SET computerid = ?,computertype = ?,personid = ? WHERE id = ?
	INSERT INTO personToComputer (id) VALUES (DEFAULT)
	UPDATE personToComputer SET computerid = ?,computertype = ?,personid = ? WHERE id = ?
	
// 3.エンティティを取得して表示する。
	// 3.1.Personのエンティティをすべて取得する。
	SELECT id FROM person
	// 3.2.Personのエンティティについて繰り返す。
		// 3.2.1.Personのエンティティに関連するComputerのエンティティを取得する。
		SELECT computerID,id,computerType FROM personToComputer WHERE personID = ?
		// 3.2.2.Computerのエンティティについて繰り返す。
		// 3.2.1.Personのエンティティに関連するComputerのエンティティを取得する。
		SELECT computerID,id,computerType FROM personToComputer WHERE personID = ?
		// 3.2.2.Computerのエンティティについて繰り返す。