Test
Scenario |
Description |
Spec |
Status |
1.1
Inheritance Single Table per Class Hierarchy Strategy |
All the class in a hierarchy are
mapped in one table with a discriminator column. 1.1.1 Specify strategy in root entity For example, Account.java has @Entity @Inheritance(strategy= InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="DCOL") then CheckingAccount is shown in one table:
For example, VIPClientAgent.java has @Entity VIPClientAgent and VIPClientAgentExt are shown in one table,
|
2.1.10.1 |
implemented |
1.2
Inheritance Joined Subclass Mapping |
The root of the class hierarchy
is represented by a single table. Each sub class is represented by a
separate table. 1.2.1 Specify strategy in root entity For example, PhoneAgent.java has @Entity @Inheritance(strategy=InheritanceType.JOINED) then PhoneAgent and PhoneAgentExt are shown in two table,
For example, BrokerageAccount with JOINED tries to overrides Account with SINGLE_TABLE. It is not supported by top-link so that one table is shown for Account and BrokerageAccount. The usage should be avoided. |
2.1.10.3 |
implemented |
1.3
Annotation Override with XML for Mapping Strategy |
Orm.xml overrides strategy in
annotation. For example, BaseInfo.java has one strategy, @Entity @Table(name="B_INFO") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="DC", discriminatorType=DiscriminatorType.STRING) @DiscriminatorValue("B_I") orm.xml has a different strategy, <entity name="BaseInfo" class="BaseInfo" access="PROPERTY"> <table name="BASE_INFO"/> <inheritance strategy="JOINED"/> <discriminator-value>BASE </discriminator-value> <discriminator-column name="INFO_TYPE"/> <exclude-default-listeners/> <exclude-superclass-listeners/> <entity-listeners/> <attributes/> </entity> The strategy in orm.xml is used. Two tables are shown as
|
10.1 6.1.2 |
implemented |
Test Scenario | Description | Spec |
Status |
2.1
Abstract Entity Class |
|
2.1.9.1 |
implemented |
2.2
Concrete Entity Class |
|
2.1.9.1 | implemented |
2.3
Abstract Mapped Superclass |
|
2.1.9.2 |
implemented |
2.4
Concrete Mapped Superclass |
|
2.1.9.2 | implemented |
2.5
Abstract Non-Entity Class |
|
2.1.9.3 |
implemented |
2.6
Concrete Non-Entity Class |
|
2.1.9.3 | implemented |
Test Scenario | Description | Spec |
Status |
3.1
Discriminator Column |
It is a column whose value
identifies the specific sub-class by the row belongs. 3.1 Specify discriminator column For example, in Account, @DiscriminatorColumn(name="DCOL") where DCOL has values of SavingsAccount, CheckingAccount, ... 3.1.2 Use default discriminator column VIPClientAgent has default DTYPE. |
2.1.9.1 9.1.30 |
implemented |
3.2
Primary Key Join Column |
ClientInfo
has @PrimaryKeyJoinColumn(name="INFO_ID") It inherits Id from BaseInfo, but mapped in this class to INFO_ID. |
9.1.32 |
implemented |
3.3
Primary Key Join Column |
A subclass needs to specified
PrimaryKeyJoinColumns when its super class has multiple primary keys
and uses JOINED strategy, For example, PhoneAgentExt has @Entity @PrimaryKeyJoinColumns({ @PrimaryKeyJoinColumn(name="PA_PK1", referencedColumnName="PK1"), @PrimaryKeyJoinColumn(name="PA_PK2", referencedColumnName="PK2") }) |
9.1.33 |
implemented |
3.4
Attribute Override |
The mapping attribute of an
inherited class is override. For example, the mapping
attribute bankName
in the CheckingAccount is
override as "bank_name", i.e. @AttributeOverride(name="bankName", column=@Column (name="BANK_NAME")) |
9.1.10 |
implemented |
3.5
Association Override |
It is used to override a
ManyToOne or OneToOne mapping property or field for an entity
relationship on a mapped supperclass. For example, Client has OneToMany relationship with BaseInfo. DummyClient overrides the relationship from baseInfo to client_info, i.e. @AssociationOverride(name="baseInfo", joinColumns=@JoinColumn (name="CLIENT_INFO")) |
9.1.12 |
implemented |
Test Scenario | Description | Spec |
Status |
4.1 Uni-directional OneToOne | OneToOne has EAGER fetch in
default, e.g. ClientInfo
can be found from Client. The Casecase Persist is used, e.g. For example, from Client to BaseInfo. @OneToOne(cascade=CascadeType.PERSIST) @JoinColumn(name="FK_INFO") public BaseInfo getBaseInfo() { |
2.1.8.3 9.1.23 |
implemented |
4.2
Uni-directional OneToMany with EAGER fetch |
OneToMany has LAZY fetch in
default. The relationship is not fetched back to a separate
JVM. Specifying EAGER fetch to get the relationship. For
example, find Account from Client. JoinTable is specified for the mapping, e.g. @OneToMany (fetch = FetchType.EAGER) @JoinTable(name="CLIENT_ACCT", joinColumns=@JoinColumn (name="C_ID", referencedColumnName="CLIENTID"), inverseJoinColumns=@JoinColumn (name="A_ID", referencedColumnName="ACCTNUM") ) |
2.1.8.5.1 9.1.24 3.2.4.2 |
implemented |
4.3
Uni-directional ManyToMany |
For example, from Client to PhoneAgent with a composite key, @ManyToMany @JoinTable(name="CLIENT_PHONEAGENT", joinColumns=@JoinColumn(name="C_ID", referencedColumnName="CLIENTID"), inverseJoinColumns={ (name="PA_ID1", referencedColumnName="PK1"), (name="PA_ID2", referencedColumnName="PK2") ) |
2.1.8.5.2 |
implemented |
4.4
Bi-directional ManyToOne |
For example, from VIPClient to VIPClientAgent with a composite key, @ManyToOne @JoinColumns ({ @JoinColumn(name="FK_VA1", referencedColumnName="PK1I"), @JoinColumn(name="FK_VA2", referencedColumnName="PK2S") }) |
2.1.8.2 | implemented |
Test Scenario | Description |
Spec |
Status |
5.1
Property Based Access |
Whole class hierarchy use
property based access, e.g. BaseAccount. |
2.1.1 |
implemented |
5.2
Field Based Access |
Other class hierarchy use field
based access, e.g. ClientInfo. |
2.1.1 |
Test Scenario | Description | Spec |
Status |
6.1
Polymorphic Query |
The instances returned by a
query include instances of the subclasses. For example, em.createQuery(SELECT a From Account a WHERE a.status = :acctStatus) .setParameter("acctStatus", Account.Status.OPEN) .getResultList(); where "Account a" is an abstract entity and has sub-classes such as CheckingAccount and SavingsAccount as long as its status is OPEN. |
3.6.5 4.4.8 |
implemented |
6.2
Eager fetch across JVM |
See 4.1 and 4.2 |
3.2.4.2 |
implemented |
Type |
Abstract |
Concrete |
Entity |
Account |
CheckingAccount
SavingsAccount BrokerageAccount MarginAccount CreditCardAccount VIPClientAgent VIPClientAgentExt PhoneAgent PhoneAgentExt ClientInfo |
Mapped Superclass |
BankAccount |
Client BaseAgent |
Plain |
BaseAccount |
BaseClient Info |
No. |
Name |
Description |
1 |
create1 |
create SavingsAccount called account1 by em.persist. |
2 |
find1 |
find
account1
with em.find(Account.class,
acctNum), in which account details are rendered to show its
subclasses. |
3 |
create2 |
create CheckingAccount called accoun2 by em.persist. |
4 |
find2 |
find account2 with em.find(Account.class, acctNum), in which account details are rendered to show its subclasses. |
5 |
create3 |
create VIPClientAgent @IdClasss for 2 keys called agent1 by em.persist, create PhoneAgent with @EmbeddedId for 2 keys called agent2 and agent3 by em.persist, create a ClientInfo, which will be Cascade.persist by VIPClient. set relationhsips so that
|
6 |
find3 |
find
client by em.find(DummyClient.class, clientId),
in which the client details are rendered to show Client, ClientInfo and
VIPClientAgent, PhoneAgent. |
7 |
create4 |
create CheckingAccount called accoun3 by em.persist. |
8 |
find4 |
find account3 by em.find(Account.class, acctNum), |
9 |
create5 |
create CreditCardAccount
called account4 by em.persit |
10 |
create6 |
create
BrokerageAccount called account5
by em.persist |
11 |
create7 |
create MarginAccount called account5 by em.persist |
12 |
create8 |
create
RegularClient by em.persist, which has account4, agent2, agent4,
and its ClientInfo |
13 |
find6 |
find the client in test 12 by em.find(DummyClient.class, clientId); |
14 |
create8 | create RegularClient by em.persist, which has account5, account6, agent2, agent4, and its ClientInfo |
15 |
find9 |
find ClientInfo in test 13 by em.find(BaseInfo.class, clientInfoId). |
16 |
update4 |
change account3 by em.find(Account.class, acctNum), account.setName(name), then em.merge(account). |
17 |
remove4 |
remove account3 by account = em.find(Account.class, acctNum), and then em.remove(account). |
18 |
native1 |
use
native query to verify the followings:
|
19 |
jpaql1 |
Polymorphic Query by String,
e.g. em.createQuery("SELECT a From Account a WHERE a.name like :acctName") .setParameter("acctName", acct1) .getResultList(); which finds one "Account a" by acctName, while "Account a" is an abstract entity with sub-classes. Polymorphic Query by Enum, e.g. em.createQuery(SELECT a From Account a WHERE a.status = :acctStatus) .setParameter("acctStatus", Account.Status.OPEN) .getResultList(); where finds all open "Account a", each of account is an abstract entity with sub-classes such as CheckingAccount and SavingsAccount. |
20 |
jpaql2 |
Update
by String, e.g. Query q = em.createQuery("Update Account a SET a.name = :acctName WHERE a.acctNum = :acctNum"); q.setParameter("acctNum", "A10001"); q.setParameter("acctName","savings-sherry"); q.executeUpdate(); which changes one account's name to "saving-sherry" while its acctNum is "A10001". Update by Enum, e.g. Query q = manager.createQuery("Update Account a SET a.status = :acctStatus WHERE LOCATE(:acctName, a.name) > 0 "); q.setParameter("acctStatus", Account.Status.OPEN); q.setParameter("acctName", "sherry"); q.executeUpdate(); which changes all accounts to status open if its name contains "sherry". |