类图和ORM关系(一)

    技术2022-05-11  77

    本文描述类图和ORM映射的关系。在例子部分,小鸡射手采用EJB 3.0 Annotation方式为主,数据库是HSQLDB。由于例子比较多,全文分三部分。   1 类图与ORM的关系 面向对象的分析类包括边界类、控制类和实体类,需要持久化的是实体类。 UML类图中,类和类的关系包括: - 关联(Associate) - 泛化(Generalize) - 聚集(Aggregate) - 复合(Compose) - 多元关联(Association)   ORM映射方式如下: - 复合关系:采用值类型(Value Type)映射,包括单个值类型和值类型集合 - 泛化关系:采用继承映射,包括:             一个继承结构使用一个表(Table per class hierarchy)             各子类使用单独的表(Table per subclass)             支持多态的各具体实体类使用单独的表(Table per concrete class with implicit polymorphism)             采用Union的各具体实体类使用单独的表(Table per concrete class with unions) - 其他关系采用关联映射,包括:             单向ManyToOne,这是最基本、最重要的关联;             单向OneToMany,这是涉及到集合的最主要关联;             双向ManyToOne;             单向OneToOne;             双向OneToOne;             单向ManyToMany;             双向ManyToMany,一般地最好实现为两个OneToMany关系;             三元关联(Association)采用中间表和Map实现。   2  值类型映射 ORM映射不是简单地将一个类映射成一个数据库表。对象模型一般是细颗粒度,例如User类和Address类是复合关系,Address类可以映射为值对象。相对于实体,值对象不需要主键(Identity),和复合关系一样,它的生命期和所属实体一致。在ORM映射中, 应该尽量使用值对象。 下面的例子描述User类和Address类的映射。简单起见实体中只包括字段定义,如果需要增加字段属性如NOT NULL,可以增加@Column(nullable = false)等,例子中均省略了。 @Embeddable public   class  Address1  {    private String street;} @Entity public   class  User1  {    @Id private int id;    private String name;    @Embedded Address1 homeAddress;} 由于Address类是值类型,数据库表只有一个: create   table  "USER1"(    "ID"  INTEGER   not   null ,   "NAME"  VARCHAR ( 255 ),   "STREET"  VARCHAR ( 255 ),     constraint  "SYS_PK_1637"  primary   key  ("ID")); create   unique   index  "SYS_PK_1637"  on  "USER1"("ID"); 如果User类中有多个Address对象,例如homeAddress和companyAddress,则需要字段更名: @Embeddable public   class  Address2  {    private String street;} @Entity public   class  User2  {    @Id private int id;    private String name;    @Embedded Address2 homeAddress;@Embedded @AttributeOverrides({ @AttributeOverride(name="street",column=@Column(name="COMPANY_STREET"))})    Address2 companyAddress;} 数据库表如下: create   table  "USER2"(    "ID"  INTEGER   not   null ,   "NAME"  VARCHAR ( 255 ),   "STREET"  VARCHAR ( 255 ),   "COMPANY_STREET"  VARCHAR ( 255 ),     constraint  "SYS_PK_1638"  primary   key  ("ID")); create   unique   index  "SYS_PK_1638"  on  "USER2"("ID");        如果希望Address类既是值类型,数据又放在单独的表中,可以采用@SecondaryTable实现: @Embeddable public   class  Address3  {    private String street;} @Entity@SecondaryTable(name  =   " USER3_ADDRESS3 " pkJoinColumns  =   {@PrimaryKeyJoinColumn(name="id")} ) public   class  User3  {    @Id private int id;    private String name;    @Embedded    @AttributeOverrides({ @AttributeOverride(name = "street", column = @Column(name="STREET", table = "USER3_ADDRESS3"))})    private Address3 homeAddress;    } 数据库表如下: create   table  "USER3"(    "ID"  INTEGER   not   null ,   "NAME"  VARCHAR ( 255 ),     constraint  "SYS_PK_1639"  primary   key  ("ID")); create   unique   index  "SYS_PK_1639"  on  "USER3"("ID"); create   table  "USER3_ADDRESS3"(    "STREET"  VARCHAR ( 255 ),   "ID"  INTEGER   not   null ,     constraint  "SYS_PK_1636"  primary   key  ("ID")); alter   table  "USER3_ADDRESS3"       add   constraint  "FKAD4A6F76C4D6A8B8"      foreign   key  ("ID")      references  "USER3"("ID"); create   unique   index  "SYS_PK_1636"  on  "USER3_ADDRESS3"("ID"); create   index  "SYS_IDX_1697"  on  "USER3_ADDRESS3"("ID");          JPA规范目前不支持值类型的集合。如果采用Hibernate,则可以使用Hibernate特有的Annotation实现值类型集合。值类型可以是简单类型(如String),也可以是Value Type(如Address);Hibernate支持的集合类型包括: Set:集合中不能包括重复的元素; Bag:集合中允许重复元素,但不是排序的; List:集合元素记录了位置信息; Map:集合元素是<key,value>,并且不是排序的; SortedSet:排序的Set集合; SortedMap:排序的Map元素; OrderedSet:数据库排序的Set集合; OrderedMap:数据库排序的Map集合; OrderedBag:数据库排序的Bag集合。 由于这不是JPA支持的特性,仅举两个例子说明。第一个例子是User类有一个String值类型的Set: @Entity public   class  User4  {    @Id private int id;    private String name;        @org.hibernate.annotations.CollectionOfElements    @JoinTable(name = "User4_Street4", joinColumns = @JoinColumn(name = "id"))    @Column(name = "street", nullable = false)    private Set<String> streets = new HashSet<String>();    } 数据库表如下: create   table  "USER4"(    "ID"  INTEGER   not   null ,   "NAME"  VARCHAR ( 255 ),     constraint  "SYS_PK_1640"  primary   key  ("ID")); create   unique   index  "SYS_PK_1640"  on  "USER4"("ID"); create   table  "USER4_STREET4"(    "ID"  INTEGER   not   null ,   "STREET"  VARCHAR ( 255 not   null ,     constraint  "SYS_PK_1641"  primary   key  ("ID","STREET")); alter   table  "USER4_STREET4"       add   constraint  "FKCAC0D3DBC4D6A8B9"      foreign   key  ("ID")      references  "USER4"("ID"); create   unique   index  "SYS_PK_1641"  on  "USER4_STREET4"("ID","STREET"); create   index  "SYS_IDX_1699"  on  "USER4_STREET4"("ID");         第二个例子是User类有一个Address值类型的Set: @Embeddable public   class  Address5  {    @org.hibernate.annotations.Parent    private User5  user;        private String street;        public User5 getUser() return user;}    public void setUser(User5 user) this.user = user;}} @Entity public   class  User5  {    @Id private int id;        private String name;        @org.hibernate.annotations.CollectionOfElements    @JoinTable(name = "User5_Address5", joinColumns = @JoinColumn(name = "id"))    private Set<Address5> addresses = new HashSet<Address5>();} 数据库表如下: create   table  "USER5"(    "ID"  INTEGER   not   null ,   "NAME"  VARCHAR ( 255 ),     constraint  "SYS_PK_1642"  primary   key  ("ID")); create   unique   index  "SYS_PK_1642"  on  "USER5"("ID"); create   table  "USER5_ADDRESS5"(    "ID"  INTEGER   not   null ,   "STREET"  VARCHAR ( 255 )); alter   table  "USER5_ADDRESS5"       add   constraint  "FKCE3D99D6C4D6A8BA"      foreign   key  ("ID")      references  "USER5"("ID"); create   index  "SYS_IDX_1701"  on  "USER5_ADDRESS5"("ID");         本文的第一部分到此结束, 类图和ORM关系(二)介绍继承的映射, 类图和ORM关系(三)介绍关联的映射。

    最新回复(0)