S2JDBC における一対多・多対一の関連と検索
Groovy 1.1 で実行できるようにした S2JDBC の環境(id:fits:20071202)で、一対多・多対一の関連の定義と検索を試してみた。
テーブル定義に使った SQL は以下の通り。EMP テーブルで外部キーを定義している。
DROP TABLE IF EXISTS DEPT; CREATE TABLE DEPT(ID INT IDENTITY PRIMARY KEY , DEPT_NO INT, DEPT_NAME VARCHAR(50), LOC VARCHAR(255), VERSION_NO INT); DROP TABLE IF EXISTS EMP; CREATE TABLE EMP(ID INT IDENTITY PRIMARY KEY , NAME VARCHAR(50), DEPT_ID INT, VERSION_NO INT, FOREIGN KEY(DEPT_ID) REFERENCES DEPT(ID));
Groovy スクリプトは以下の通り。エンティティクラスの定義・新規登録・検索を実施している。
import java.util.List import javax.persistence.* import org.seasar.framework.container.SingletonS2Container import org.seasar.framework.container.factory.SingletonS2ContainerFactory import org.seasar.extension.jdbc.JdbcManager @Entity class Dept { @Id @GeneratedValue Integer id Integer deptNo String deptName String loc //一対多の設定(mappedBy で Emp クラスの dept プロパティを指定) @OneToMany(mappedBy = "dept") List<Emp> empList @Version Integer versionNo } @Entity class Emp { @Id @GeneratedValue Integer id String name Integer deptId //多対一の設定 @ManyToOne Dept dept @Version Integer versionNo } SingletonS2ContainerFactory.init() def jdbcManager = SingletonS2Container.getComponent(JdbcManager.class) //Dept を作成して DB に新規登録 def createDept = {deptNo, deptName -> def deptData = new Dept(deptNo : deptNo, deptName : deptName) jdbcManager.insert(deptData).execute() deptData.id } //Emp を作成して DB に新規登録 def createEmp = {name, deptId -> def empData = new Emp(name : name, deptId : deptId) jdbcManager.insert(empData).execute() empData.id } def deptId = createDept(1, "部署1") createDept(2, "部署2") createDept(3, "部署3") def empId = createEmp("従業員1", deptId) createEmp("従業員2", deptId) createEmp("従業員3", deptId) println "------ Dept ----------" //Dept を検索(一対多関連の Emp 情報を含む) def dept1 = jdbcManager.from(Dept.class).leftOuterJoin("empList").where("id = ?", deptId).getSingleResult() println "Dept id=${dept1.id}, name=${dept1.deptName}, emp size=${dept1.empList.size}" dept1.empList.each { println " - emp id=${it.id}, name=${it.name}, dept=${it.dept}" } println "------ Emp ----------" //Emp を検索(多対一関連の Dept 情報を含む) def emp1 = jdbcManager.from(Emp.class).leftOuterJoin("dept").where("id = ?", empId).getSingleResult() println "Emp id=${emp1.id}, name=${emp1.name}, deptName=${emp1.dept.deptName}, dept.empList.size=${emp1.dept.empList.size}(${emp1.dept.empList[0].name})"
一対多や多対一を検索する際、join 系のメソッド(join、innerJoin、leftOuterJoin)を結合するプロパティを指定して呼び出す。
例えば、Dept の検索で leftOuterJoin("empList") の呼び出しが無いと、取得した Dept オブジェクトの empList プロパティの値は null になる。
なお、上記を実行した結果は以下の通り。
------ Dept ---------- Dept id=1, name=部署1, emp size=3 - emp id=1, name=従業員1, dept=Dept@e93999 - emp id=2, name=従業員2, dept=Dept@e93999 - emp id=3, name=従業員3, dept=Dept@e93999 ------ Emp ---------- Emp id=1, name=従業員1, deptName=部署1, dept.empList.size=1(従業員1)