I am not sure I like this. We now require creation of some sort of
BuilderIgniteObjectView, which looks a bit over the top for me.

How about using the hasher to calculate the hash-code and setting it into
the builder manually in your implementation? To my knowledge, builder
allows you to get individual field values, so you can get all the values
required to calculate the hash value:

For example, here is what a hasher can look like:

—————-
interface JdbcTypeHasher {
    int hashCode(Collection<?> values);
}
—————-

Then, somewhere in your code, you will set the hash-code on the builder
yourself:

—————
IgniteObjectBuilder builder = …; // initialize

Collection<?> c = new ArrayList<>();

for (each field required for hash) {
    c.add(builder.getField(name));
}

int hash = hasher.hashCode(c);

builder.hashCode(hash); // Set hash-code on the builder.
——————

Thoughts?

D.

On Thu, Oct 29, 2015 at 7:23 AM, Alexey Kuznetsov <[email protected]>
wrote:

> Alexey,
>
> I like this very much, this almost solve my problems and I do not need any
> fabrics!
>
> Thanks!
>
> On Thu, Oct 29, 2015 at 9:19 PM, Alexey Goncharuk <
> [email protected]> wrote:
>
> > Alexey,
> >
> > What if we create a thin wrapper around PortableBuilder that implements
> > IgniteObject? Since PortableBuilder already has getField() method, you
> only
> > need to delegate to a builder in this wrapper. Then we can invoke the
> > interface Dmitriy suggested, obtain hashCode and set it back to the
> > builder.
> >
> > In pseudo-code:
> >
> > PortableBuilder bld = getBuilder();
> >
> > populateFromResultSet(bld);
> >
> > IgniteObject bldView = new BuilderIgniteObjectView(bld);
> >
> > int hashCode = hashBuilder.hashCode(bldView);
> > bld.hashCode(hashCode);
> >
> > bld.build();
> >
> >
> > Thoughts?
> >
> > 2015-10-29 16:34 GMT+03:00 Alexey Kuznetsov <[email protected]>:
> >
> > > Dmitriy,
> > >
> > > > How about adding JdbcTypeHasher interface, which will look like this:
> > > > interface JdbcTypeHasher {
> > > >    public int hashCode(IgniteObject o, Collection<String> fields);
> > > >}
> > > > User should be optionally set this interface at the JdbcType level.
> If
> > > not
> > > > set, then we use our default implementation.
> > > > Will this work?
> > >
> > > First I thought it will work, but when I started to implement hasher
> > > support I faced several problems:
> > >   1) IgniteObject/PortableObject is actually immutable, so setting
> > hashcode
> > > for already constructed object looks dirty (set several bytes in array
> at
> > > certain offset).
> > >   2) It is not very efficient from implementation point of jdbc pojo
> > store
> > > (on more cycle over object fields with not very efficient access by
> name)
> > >
> > > So, I came to this solution:
> > >
> > > // Hash builder.
> > > public interface JdbcTypeHashBuilder {
> > >     // Calculate hash code for specified value and field name.
> > >     public int toHash(Object val, String typeName, String fieldName);
> > >
> > >     // Calculated hash code.
> > >     public int hash();
> > > }
> > >
> > > // Default implementation of JdbcTypeHashBuilder. User could implement
> > its
> > > own if needed.
> > > public class JdbcTypeDefaultHashBuilder implements JdbcTypeHashBuilder
> {
> > >     private int hash = 0;
> > >
> > >     @Override public int toHash(Object val, String typeName, String
> > > fieldName) {
> > >         hash = 31 * hash + (val != null ? val.hashCode() : 0);
> > >
> > >         return hash;
> > >     }
> > >
> > >     @Override public int hash() {
> > >         return hash;
> > >     }
> > > }
> > >
> > > // Factory for creating default hash builder:
> > > public class JdbcTypeDefaultHashBuilderFactory implements
> > > Factory<JdbcTypeHashBuilder> {
> > >     private static final long serialVersionUID = 0L;
> > >
> > >     /** Instance of factory for reuse. */
> > >     public final static JdbcTypeDefaultHashBuilderFactory INSTANCE =
> new
> > > JdbcTypeDefaultHashBuilderFactory();
> > >
> > >     @Override public JdbcTypeHashBuilder create() {
> > >         return new JdbcTypeDefaultHashBuilder();
> > >     }
> > > }
> > >
> > > And I add factory to CacheJdbcPojoStoreConfiguration {
> > > ....
> > >   private Factory<JdbcTypeHashBuilder> hashBuilderFactory =
> > > JdbcTypeDefaultHashBuilderFactory.INSTANCE;
> > > }
> > >
> > > Now I could build PortableObject and calculate its hash at the same
> time:
> > > ...
> > > portableBuilder = ...
> > >
> > > hashBuilder = factory.create();
> > >
> > > for (dbField: dbFields) {
> > >   Object val = dbField.getValue();
> > >
> > >  portableBuilder.setField(dbField.getJavaName(), val) ;
> > >  hashBuilder.toHash(val, typeName, dbField.getJavaName());
> > > }
> > >
> > > return portableBuilder.hashCode(hashBuilder.hash()).build();
> > >
> > > Thoughts?
> > >
> > > --
> > > Alexey Kuznetsov
> > > GridGain Systems
> > > www.gridgain.com
> > >
> >
>
>
>
> --
> Alexey Kuznetsov
> GridGain Systems
> www.gridgain.com
>

Reply via email to