1 2 Previous Next 20 Replies Latest reply on Sep 24, 2008 4:14 AM by adamw Go to original post
      • 15. Re: Storing/restoring diffs; GDIFF
        genman

        Varchar is max 2-8k for most dbms. Most rows are limited to 64k bytes. So I'd think it unlikely you'd want to capture diffs for varchar.

        You can Proxy abstract classes as well as interfaces. I think Javassist won't work for String, as it's declared final. Proxy could work with CharSequence.

        I admit Clob/Blobs are shitty interfaces to work with.

        • 16. Re: Storing/restoring diffs; GDIFF
          adamw

          You're right that maybe it's not very useful to diff a varchar, but does supproting clobs/blobs and varchars make any implementation difference?

          Using CharSequence may be a good way out. But that would require the user to declare the field in the entity as of that type, wouldn't it?

          --
          Adam

          • 17. Re: Storing/restoring diffs; GDIFF
            genman

            Hey Adam, I've been otherwise occupied...

            To answer that question, yes you'd have to declare a type that is "non-final". You could intercept the getter method (using AOP) that returns the String as well.

            I'm thinking, though, you could also just replace the value using a "post-load" event handler. But you'd lose any sort of "lazy loading." Which is probably acceptable, but worth mentioning I suppose.

            I'm a bit lost when it comes to where to inject the proxy/resolved version. I added an event listener to VersionsEventListener to capture "post-load" events. This seemed to be the only place to inject.

            I'm guessing I have to scan the property names, look for @Versioned(modStore=DIFF) (though that "flag" be pre-computed and stored in EntityConfiguration), and replace the value in the entity with a proxied version post load.

            One nice thing is the current revision of an entity doesn't need to have the text/byte value (clob/blob) proxied. But it'd be nice to somehow store the database's value for future processing. (Is there someplace in the Hibernate session to store data?)

            EntityConfiguration would have a reference to the configured algorithm strategy. Upon persist/update/delete, there would be a call to a "ContentMapper" (something similar to the PropertyMapper) that replaces the versioned values with "diff" values.

            The versioned entity load would also trigger a "post-load" event which would get intercepted by envers. If the entity was versioned, it would have to load all the versions newer than it, then apply patches backwards.

            Does this make sense?

            • 18. Re: Storing/restoring diffs; GDIFF
              adamw

              Hello,

              as for the accepted types of fileds. Maybe we could have a hybrid solution, that is, when the type of the field is a String, eagerly load the value, and when it is a CharSequence/anything mutable load it lazily. In the "diff-usage" manual there would also be a note saying that CharSequence-s are preferable :).

              I'm not sure using post-load events is necessary. For historical data, you can just modify SinglePropertyMapper.mapToEntityFromMap to check the modStore and create a proxy/eagerly load the changes. For current data, as you say, that is not necessary, as the current value would be stored in "full". The only thing I don't understand is what you mean by "But it'd be nice to somehow store the database's value for future processing"? :)

              --
              Adam

              • 19. Re: Storing/restoring diffs; GDIFF
                genman

                What I mean is, after you load the entity you need to copy that entity as-is into the session so that when the new version is modified, you can generate the comparison. Otherwise, you have to do a fetch to the database. Does Hibernate keep the original entity object in memory?

                • 20. Re: Storing/restoring diffs; GDIFF
                  adamw

                  Luckily Hibernate stores the old version for you. If you look at the event listeners data (for ex. PostListenerEvent), you'll see that it has both "state" and "oldState" arrays. This is used in the mappers, and in the PropertyMapper you have access both to the new and old state, here's a signature of the method:

                  mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj)

                  So I think you'd need to check the modStore and either put "newObj" in the map or a diff between "newObj" and "oldObj".

                  --
                  Adam

                  1 2 Previous Next