Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Examples/JPA/TemporalEntity"

(Schema Generation)
(Create Current Person)
Line 86: Line 86:
 
</source>
 
</source>
  
'Note: The INSERT followed by the UPDATE statement are to populate the self-referencing FK values. Optimized solution being investigated'
+
''Note: The INSERT followed by the UPDATE statement are to populate the self-referencing FK values. Optimized solution being investigated''
  
 
=== Create Person Edition ==
 
=== Create Person Edition ==

Revision as of 16:04, 20 October 2011

bug 361016

EclipseLink JPA Futures Example

This example is intended to illustrate how entity versions can be stored and queried in a database. Unlike the history functionality of EclipseLink this example is focused on creating versions of an entity that may take effect in the future.

Requirements

  • Optimize queries against current version. Queries against future versions
  • Allow versions for the future to be created with a time they are expected to become the current
  • When a future version is promoted to current its temporal storage is not required (no history remains)
  • Allow multiple future versions and support changing when a future version takes effect
  • Support defining a new entity that does not yet exist but may exist in the future

Software

This example is being built using EclipseLink 2.3.1. To access the source of the example check it out of SVN at:

/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.futures

How it Works

Coming Soon...

Examples

The following examples are from test cases.

Schema Generation

At the start of each test suite the schema is replaced. The resulting CREATE TABLE operations are:

CREATE TABLE TPERSON (OID NUMBER(10) NOT NULL, 
                      END_TS NUMBER(19) NULL, 
                      F_NAME VARCHAR2(255) NULL, 
                      L_NAME VARCHAR2(255) NULL, 
                      START_TS NUMBER(19) NULL, 
                      CID NUMBER(10) NULL, 
                      ADDRESS_OID NUMBER(10) NULL, 
                      PRIMARY KEY (OID))
 
CREATE TABLE TADDRESS (OID NUMBER(10) NOT NULL, 
                       CITY VARCHAR2(255) NULL, 
                       END_TS NUMBER(19) NULL, 
                       START_TS NUMBER(19) NULL, 
                       STATE VARCHAR2(255) NULL, 
                       STREET VARCHAR2(255) NULL, 
                       CID NUMBER(10) NULL, 
                       PRIMARY KEY (OID))
 
ALTER TABLE TPERSON ADD CONSTRAINT FK_TPERSON_ADDRESS_OID FOREIGN KEY (ADDRESS_OID) REFERENCES TADDRESS (OID)
 
ALTER TABLE TPERSON ADD CONSTRAINT FK_TPERSON_CID FOREIGN KEY (CID) REFERENCES TPERSON (OID)
 
ALTER TABLE TADDRESS ADD CONSTRAINT FK_TADDRESS_CID FOREIGN KEY (CID) REFERENCES TADDRESS (OID)

Create Current Person

Person p = new Person();
p.setFirstName("Doug");
p.setLastName("Clarke");
 
Address a = new Address();
a.setStreet("45 O'Connor Street");
a.setCity("Ottawa");
a.setState("Ontario");
 
p.setAddress(a);
em.persist(a);
em.persist(p);

Resulting SQL:

[EL Fine]: INSERT INTO TADDRESS (OID, CITY, END_TS, START_TS, STATE, STREET, CID) VALUES (?, ?, ?, ?, ?, ?, ?)
	bind => [1, Ottawa, 9223372036854775807, 0, Ontario, 45 OConnor Street, NULL]
[EL Fine]: UPDATE TADDRESS SET STATE = ?, STREET = ?, CID = ?, CITY = ? WHERE (OID = ?)
	bind => [Ontario, 45 OConnor Street, 1, Ottawa, 1]
[EL Fine]: INSERT INTO TPERSON (OID, END_TS, F_NAME, L_NAME, START_TS, CID, ADDRESS_OID) VALUES (?, ?, ?, ?, ?, ?, ?)
	bind => [2, 9223372036854775807, Doug, Clarke, 0, NULL, NULL]
[EL Fine]: UPDATE TPERSON SET CID = ?, ADDRESS_OID = ?, F_NAME = ?, L_NAME = ? WHERE (OID = ?)
	bind => [2, 1, Doug, Clarke, 2]

Note: The INSERT followed by the UPDATE statement are to populate the self-referencing FK values. Optimized solution being investigated

= Create Person Edition

This example creates an edition of a current Person (id={currentPersonId}) which is set to take effect at T2 and be deleted or replaced at T4. The current version of the person is updated accordingly to end at T2.

Person currentPerson = em.find(Person.class, currentPersonId);
 
Person p = TemporalHelper.createEdition(em, currentPerson);
p.setFirstName("Dougie");
p.setStart(T2);
currentPerson.setEnd(T2);
p.setEnd(T4);
em.persist(p);

SQL:

...

Create Future Person

This creates a new Person that does not currently exist but will exist as of T3.

Person p = new Person();
p.setFirstName("John");
p.setLastName("Doe");
p.setStart(T3);
em.persist(p);

SQL:

[EL Fine]: INSERT INTO TPERSON (OID, END_TS, F_NAME, L_NAME, START_TS, CID, ADDRESS_OID) VALUES (?, ?, ?, ?, ?, ?, ?)
	bind => [1, 9223372036854775807, John, Doe, 3, NULL, NULL]
[EL Fine]: UPDATE TPERSON SET CID = ?, START_TS = ?, F_NAME = ?, L_NAME = ? WHERE (OID = ?)
	bind => [1, 3, John, Doe, 1]

Query for Current Person

 

SQL:

 

Find Current Person

Person person = em.find(Person.class, currentPersonId);
System.out.println("FIND CURRENT: " + person);

LOG:

[EL Fine]: SELECT OID, CITY, END_TS, START_TS, STATE, STREET, CID FROM TADDRESS WHERE ((OID = ?) AND (START_TS = ?))
	bind => [1, 0]
FIND CURRENT: model.Person(2)::Doug @ 0-2

Query all Current Persons

List<Person> results = em.createQuery("SELECT p From Person p", Person.class).getResultList();

LOG:

[EL Fine]: SELECT OID, END_TS, F_NAME, L_NAME, START_TS, CID, ADDRESS_OID FROM TPERSON WHERE (START_TS = ?)
	bind => [0]

Find Person edition @ T3

Map<String, Object> props = new HashMap<String, Object>();
props.put("EFF_TS", T3);
EntityManager em = emf.createEntityManager(props);
 
Person personEdition = em.createQuery("SELECT p From PersonEdition p WHERE p.cid = " + currentPersonId, Person.class).getSingleResult();
 
System.out.println("QUERY EFFECTIVE @ T3: " + personEdition);

Log Output:

[EL Fine]: SELECT OID, END_TS, F_NAME, L_NAME, START_TS, CID, ADDRESS_OID FROM TPERSON WHERE ((CID = ?) AND ((? >= START_TS) AND (? < END_TS)))
	bind => [2, 3, 3]
QUERY EFFECTIVE @ T3:
Person(3)::Dougie @ 2-4

Back to the top