In the next several trails, we develop a new investment calculator application to demonstrate how to use EJB 3.0 entity beans. The new investment calculator allows you to save a list of fund company profiles and a list of individual investor profiles in a relational database. For each investment calculation, you can choose a company and an individual from the database, and then enter a monthly saving amount to calculate the final investment return. Each calculation record is also saved in the database with a time stamp. We can later search and update the calculation records in the database.
在下面的几节中,我们将开发出一个全新的投资计算器以展示如何使用实体BEAN,这个新的投资计算器允许你在关系数据库中保存一个fund company profiles列表和一个individual investor profiles列表。对于每一次的投资计算,你都可以从DB中选择一个company和一个individual,然后输入每月的存款来计算最终的投资回报。每一次的计算记录用一个time stamp保存到DB中。这样,我们可以在以后search和update这些记录。
We construct the following object class hierarchy to model the data in the above investment calculator application. All classes conform to simple JavaBeans convention (i.e., standard getter and setter methods for data attributes).
我们将构建如下的object class体系来模拟上面所说的投资计算器。它们都遵循简单的javabean规范(setter, getter).
Fund类表示profiles of available investment funds。它有一个name和一个average annual growth rate属性
Investor类表示profiles of individual investors.它有如下的数据属性:投资者的name, 投资的start age, 投资的end age
Record类表示一次investment calculation。它有如下数据属性:一个Fund,一个Investor,一个monthly saving amount, 还有一个final result.
TimedRecord类表示一次以time stamp标记的calculation record, 它继承自Record类,并增加了一个timestamp类型的属性。
@Entity
@Table(name
=
"
fund
"
)
public
class
Fund
implements
Serializable {
private
int
id;
private
String name;
private
double
growthrate;
public
Fund () { }
public
Fund (String name,
double
growthrate) {
this
.name
=
name;
this
.growthrate
=
growthrate;
}
@Id
@GeneratedValue
public
int
getId () {
return
id;
}
public
void
setId (
int
id) {
this
.id
=
id;
}
public
String getName () {
return
name;
}
public
void
setName (String name) {
this
.name
=
name;
}
//
Other getter and setter methods
}
@Id 表示Id是表的主键
@GeneratedValue表示主键的值由Server自动生成。
你可以显示的给每一个属性指定它所对应的column,column的默认值同属性的名字。
生成的schema如下图所示:
Investor类与Fund类似,这里不再表述。
Record实体bean比较Fund和Investor都要复杂,它不仅包括简单的数据属性,还包括其它bean(比如Fund和Investor)自身,为了表达它们之间的关系,在Record表中含有对应的外键(关联到Fund和Investor的主键)。你可以在Record Class中使用标注@JoinColumn来表示这些外键,如果你忘了写,EJB 3.0 server会给你指定一个默认的column.
标注还可以用来表示外键之间的约束关系。比如
@ManyToOne
@OneToMany
@OneToOne:
@ManyToMany
@Entity
@Table(name
=
"
record
"
)
//
public
class
Record
implements
Serializable {
protected
int
id;
protected
Fund fund;
protected
Investor investor;
protected
double
saving;
protected
double
result;
//
@ManyToOne(optional
=
false
)
@JoinColumn(name
=
"
my_fundid
"
)
public
Fund getFund () {
return
fund;
}
@ManyToOne(optional
=
false
)
//
Use the system-specified join column
public
Investor getInvestor () {
return
investor;
}
//
Other getter and setter methods
}
TimedRecord类继承Record,有多种方式映射继承关系。比如,你可以给继承体系中的每一个类一个独立的表然后使用外键来约束它们之间的关系。在这个示例中,我们使用另外一种映射策略---单表映射策略。
single table mapping strategy是EJB3.0中默认的继承映射策略。它把基类Record和子类TimedRecord映射到同一张表。这张表中含有所有类中的所有属性。用一个特殊的列来区分是哪一个子类。
必须在基类中指定Mapping Strategy和differentiator column !我们分别用@DiscriminatorColumn 和 @DiscriminatorValue来标注,在这个例子中,Record表中的 record_type表示 differentiator, 如果它的值是B,则表示它是基类Record
@Entity
@Table(name
=
"
record
"
)
@DiscriminatorColumn(name
=
"
record_type
"
)
@DiscriminatorValue(value
=
"
B
"
)
public
class
Record {
//
}
TimedRecord 类简单的继承自 Record class.它的@DiscriminatorValue表明所有的TimedRecord在record_type这一列上的值为T
@Entity
@DiscriminatorValue (value
=
"
T
"
)
public
class
TimedRecord
extends
Record {
private
Timestamp ts;
//
public
Timestamp getTs () {
return
ts;
}
public
void
setTs (Timestamp ts) {
this
.ts
=
ts;
}
}