首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

在toplink中投射nested table

2012-10-23 
在toplink中映射nested tablenested table是Oracle所特有的一种实现,作为被Oracle收购了的OR-Mapping工具T

在toplink中映射nested table

nested table是Oracle所特有的一种实现,作为被Oracle收购了的OR-Mapping工具Toplink,自然也应该对其提供支持。但是在寻找这个的过程中,又一次深深体会到了Toplink文档的稀少(OTN,也只有OTN)以及语焉不详(我就不信有人看着官方文档能调出来的)。为以后起见,这里记录一下吧。

?

假设有以下的nested table:

?

CREATE OR REPLACE TYPE STUDENT_TYPE AS OBJECT(  STUDENT_ID   NUMBER(4),  STUDENT_NAME VARCHAR2(10));CREATE OR REPLACE TYPE STUDENT_LIST IS TABLE OF STUDENT_TYPE;CREATE TABLE SCHOOL(SCHOOL_ID NUMBER(2) primary key, SCHOOL_NAME VARCHAR2(14), STUDENTS STUDENT_LIST) NESTED TABLE STUDENTS store AS STUDENTS_TAB;ALTER TABLE STUDENTS_TAB add CONSTRAINT UK_STUDENTS_TAB UNIQUE(STUDENT_ID);

?

和以下的JO

public class School {    private int id;    private String name;    private List<Student> students;    //skip  getter, setter}

?

public class Student {    private int id;    private String name;    // skip getter,setter            }

?

那么相应的Descriptor应该这么写

?

?

 public ClassDescriptor buildSchoolDescriptor() {        ObjectRelationalDescriptor descriptor = new ObjectRelationalDescriptor();        descriptor.setJavaClass(School.class);        descriptor.addTableName("SCHOOL");        descriptor.addPrimaryKeyFieldName("SCHOOL.SCHOOL_ID");        DirectToFieldMapping idMapping = new DirectToFieldMapping();        idMapping.setAttributeName("id");        idMapping.setFieldName("SCHOOL_ID");        descriptor.addMapping(idMapping);        DirectToFieldMapping nameMapping = new DirectToFieldMapping();        nameMapping.setAttributeName("name");        nameMapping.setFieldName("SCHOOL.SCHOOL_NAME");        descriptor.addMapping(nameMapping);        ObjectArrayMapping studentsMapping = new ObjectArrayMapping();        studentsMapping.setReferenceClass(Student.class);        studentsMapping.setAttributeName("students");        studentsMapping.setFieldName("STUDENTS");        studentsMapping.setStructureName("STUDENT_LIST");        descriptor.addMapping(studentsMapping);        return descriptor;    }

?

 public ClassDescriptor buildStudentDescriptor() {        ObjectRelationalDescriptor descriptor = new ObjectRelationalDescriptor();        descriptor.setJavaClass(Student.class);        descriptor.descriptorIsAggregate();        descriptor.setStructureName("STUDENT_TYPE");        descriptor.addPrimaryKeyFieldName("id");        descriptor.addFieldOrdering("id");        descriptor.addFieldOrdering("name");        descriptor.addDirectMapping("id", "id");        descriptor.addDirectMapping("name", "name");        return descriptor;    }

?

相应的测试代码如下

 Server server = project.createServerSession();        server.login();        UnitOfWork uow = server.acquireUnitOfWork();        ClientSession cs = server.acquireClientSession();        server.shouldLogMessages();        uow.shouldLogMessages();        uow.setLogLevel(1);        School school = new School();        school.setId(1);        school=(School)uow.readObject(school);        System.out.println(school.getStudents().get(0).getId());        school.getStudents().get(0).setName("NN");        uow.commit();

?

?

在这个问题上我花了一整天时间,主要是在官方文档这里完全没有把和核心讲出来。

1,正如论坛jsuther所言,

?

In TopLink if the nested table is of refs, then you use the NestedTableMapping (target class is not aggregate), if it is a nested table or varray of object types, then you use the ObjectArrayMapping (target class is aggregate).

也就是说,所谓的NestedTableMapping,居然只对ref nested table有效,普通的nested table应该用ObjectArrayMapping, 这是何等跳跃的思维啊!

?

2 在Student Descriptor中,一定要有以下两句,不然会报ora-17049 "Inconsistent java and sql object types"

descriptor.addFieldOrdering("id");descriptor.addFieldOrdering("name");

?

3.还是在Student Descriptor中,添加DirectMapping时一定要写成以下方式,

 descriptor.addDirectMapping("id", "id"); descriptor.addDirectMapping("name", "name");

??? 切忌写成以下这样

descriptor.addDirectMapping("id", "STUDENT_ID");

?? 这里我没有去看源码,既然addDirectMapping添加的是一个哑元(不要求指定数据库Column name) 又要求指定fieldOrdering,估计在组装对象时是按顺序来的,也就是把STUDENT_TYPE中出现的属性依照addFieldOrdering依次塞给Student上的属性。为了验证这个猜想,把addFieldOrdering的顺序颠倒一下变成

descriptor.addFieldOrdering("name");descriptor.addFieldOrdering("id");

?

果然报了java.lang.NumberFormatException: For input string: "NN",验证了我的猜想

热点排行