类图和ORM关系(一)

本文描述类图和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关系(三)介绍关联的映射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值