IMO, a generic sync process should be:
* First stage : *upload* # client fetch local changes occured since last sync # client send the changes to server # server apply the changes and generate conflict report # client mark the upload success or process the conflict report # if no conflict, goto second stage
* Second stage : *download* # client fetch remote changes occured since last sync # server send the changes to client # client apply the changes and generate conflict report # client mark the download success or process the conflict report
----
For each committed transaction, if any changes occured, Envers will generate a revision record in database.
When * upload * , if no conflicts or errors, a client id should be persisted on server with a new server revision number. So the persisted revision info should including: {code} revisionNumber clientId {code}
When * download * , if no conflicts or errors, the server revision number should be persisted on client with a new client revision number. So the persisted revision info should including: {code} revisionNumber serverRevisionNumber {code}
To select the changes from * client * : {code:title=Select last sync rev} SELECT MAX(ri.revisionNumber) FROM revinfo ri WHERE ri.serverRevisionNumber IS NOT NULL {code}
{code:title=Select incremental Inserts} SELECT e FROM Entity e WHERE e.id IN ( SELECT er.originalId.id FROM AuditEntity er WHERE er.REVTYPE = ADD AND er.originalId.REV.id > :lastSyncRev ) {code}
{code:title=Select incremental Updates} SELECT e FROM Entity e WHERE e.id IN ( SELECT er.originalId.id FROM AuditEntity er WHERE er.REVTYPE = MOD AND er.originalId.REV.id > :lastSyncRev ) AND e.id NOT IN( SELECT er.originalId.id FROM AuditEntity er WHERE er.REVTYPE = ADD AND er.originalId.REV.id > :lastSyncRev ) {code}
{code:title=Select incremental Deletes} SELECT er FROM AuditEntity er WHERE er.REVEND = ( SELECT ier.originalId.REV.id FROM AuditEntity ier WHERE ier.REVTYPE = DEL AND ier.originalId.REV.id > :lastSyncRev ) {code}
To select the changes from * server * : {code:title=Select last sync rev} SELECT MAX(ri.revisionNumber) FROM revinfo ri WHERE ri.clientId = :clientId {code}
{code:title=Select max sync rev} SELECT MAX(ri.revisionNumber) FROM revinfo ri WHERE ri.clientId != :clientId OR ri.clientId IS NULL {code}
{code:title=Select incremental Inserts} SELECT e FROM Entity e WHERE e.id IN ( SELECT er.originalId.id FROM AuditEntity er WHERE er.REVTYPE = ADD AND er.originalId.REV.id > :lastSyncRev AND er.originalId.REV.id <= maxSyncRev AND ( er.originalId.REV.clientId != :clientId OR er.originalId.REV.clientId IS NULL ) ) {code}
{code:title=Select incremental Updates} SELECT e FROM Entity e WHERE e.id IN ( SELECT er.originalId.id FROM AuditEntity er WHERE er.REVTYPE = MOD AND er.originalId.REV.id > :lastSyncRev AND er.originalId.REV.id <= :maxSyncRev AND ( er.originalId.REV.clientId != :clientId OR er.originalId.REV.clientId IS NULL ) ) AND e.id NOT IN( SELECT er.originalId.id FROM AuditEntity er WHERE er.REVTYPE = ADD AND er.originalId.REV.id > :lastSyncRev AND er.originalId.REV.id <= :maxSyncRev AND ( er.originalId.REV.clientId != :clientId OR er.originalId.REV.clientId IS NULL ) ) {code}
{code:title=Select incremental Deletes} SELECT er FROM AuditEntity er WHERE er.REVEND = ( SELECT ier.originalId.REV.id FROM AuditEntity ier WHERE ier.REVTYPE = DEL AND ier.originalId.REV.id > :lastSyncRev AND ier.originalId.REV.id <= :maxSyncRev AND ( ier.originalId.REV.clientId != :clientId OR ier.originalId.REV.clientId IS NULL ) ) {code}
---- REFERENCES: # [Microsoft Sync Framework|http://msdn.microsoft.com/en-us/library/bb902854.aspx] # [Hibernate Envers|http://docs.jboss.org/hibernate/envers/3.6/reference/en-US/html_single/]
|